22 面向对象 ---
属性, 类方法, 静态方法, 反射
一. 属性
1. 属性的定义: 将方法伪装成属性, 虽然在代码层面上没有任何高深之处, 但让其看起来更合理. (类似于属性的方法)
- class Person:
- def __init__(self,name,weight,height):
- self.name=name
- self.weight=weight
- self.height=height
- @property
- def bmi(self):
- return self.weight/self.height**2
- p1=Person("吉喆嚞",56,1.65)
- # print(p1.bmi()) # 20.569329660238754 (不加 @property)
- print(p1.bmi) # 20.569329660238754 (加 @property)
2. 由于新式类中具有三种访问方式, 我们可以根据他们几个属性的访问特点, 分别将三个方法定义为对同一个属性: 获取, 修改, 删除
- class Goods:
- def __init__(self,original_price,discount):
- self.original_price=original_price
- self.discount=discount
- @property #获取
- def price(self):
- return self.original_price*self.discount
- @price.setter #修改
- def price(self,new_price):
- self.original_price=new_price
- @price.deleter #删除
- def price(self):
- del self.discount
- g1=Goods(5,0.80) # 实例化一个对象
- print(g1.price()) # 不加 @property 的用法 4.0
- print(g1.price) # 自动执行 @property 下的函数 4.0
- g1.original_price=10 # 自动执行 @price.setter 下面的函数 将原价改为 10
- print(g1.price) # 8
- del g1.discount # 自动执行 @price.deleter 下面的函数
- print(g1.discount) # 'Goods' object has no attribute 'discount'
二. 方法
方法包括: 普通方法, 静态方法和类方法, 三种方法在内存中都归属于类, 区别在于调用方式不同
1. 普通方法: 由对象调用; 至少一个 self 参数; 执行普通方法时, 自动将调用该方法的对象赋值给 self;
2. 类方法 : 由类调用; 至少一个 cls 参数; 执行类方法时, 自动将调用该方法的类复制给 cls; 对象如果调用类方法, 也是自动
将类空间传给 cls, 不是把对象空间传给 cls.
@classmethod
def class_func(cls): 定义类方法, 至少有一个 cls 参数
类名. class_func() 调用类方法
- class A:
- __name = 'alex'
- def func(self):
- print(self,'in func')
- @classmethod # 类方法
- def func1(cls):
- print(cls, 'in func1')
- a1=A()
- a1.func() #<__main__.A object at 0x0000011792F389E8> in func
- A.func(a1) #<__main__.A object at 0x0000011792F389E8> in func
- A.func1() #<class '__main__.A'> in func1 自动给 cls 传类空间
- a1.func1() #<class '__main__.A'> in func1 对象调用也是自动传类空间
- # 什么情况下使用类方法?
- # 直接让类去操作类中的方法, 没有必要创建对象在操作的时候, 用类方法.
3. 静态方法: 由类调用; 无默认参数 在类中定义一个静态方法, 无需传入你的类空间, 对象空间, 可以当成普通函数去用.
- @staticmethod
- def static_func():
类名. static_func()
- class A:
- __name = 'alex'
- def func(self):
- print(self,'in func')
- @classmethod # 类方法
- def func1(cls):
- print(cls, 'in func1')
- @staticmethod
- def login(username,password):
- print("登陆成功")
- A.login("alex","123")
相同点 : 对于所有的方法而言, 均属于类 (非对象) 中, 所以在内存中也只保存一份.
不同点 : 方法调用者不同, 调用方法时自动传入的参数不同
三. 反射
1. 反射的定义 通过字符串操作对象相关属性; python 中的一切事物都是对象(都可以使用反射)
2. 反射一共有四种 (四个可以实现自省的函数)
getattr 获取这个属性对应的值
hasattr 判断此对象中有没有这个属性
setattr 设置属性
delattr 对一个对象属性进行删除
3. 用法:
(1). 实例化一个对象
- class A:
- country = 'China'
- def __init__(self, name, age):
- self.name = name
- self.age = age
- a1 = A('alex', 1000)
- print(getattr(a1,"country")) # China
- print(getattr(a1,"name")) # alex
- print(hasattr(a1,"age")) # True
- setattr(a1,"sex","男")
- print(getattr(a1,"sex")) # 男
- delattr(a1,"name")
- print(getattr(a1,"name")) # 'A' object has no attribute 'name'
- if hasattr(a1,"name1"):
- print(getattr(a1,'name1'))
- else:
- print("没有...") # 没有
(2). 对类的示例
- class A:
- country = 'China'
- job = 'student'
- def __init__(self, name, age):
- self.name = name
- self.age = age
- def func(self):
- print('in func')
- content=input("<<<") # 输入的是 字符串
- if hasattr(A,content): # 相当于 if hasattr(A,"字符串")
- print(getattr(A,content))
- print(getattr(A,"func")) # <function A.func at 0x00000145E4F99AE8>
- print(getattr(A,"func")(11)) # in func None (默认返回 None)
- print(getattr(A,"job")) # student
- print(getattr(A,"job1","False")) # False
- print(getattr(A,"job1")) # 报错 type object 'A' has no attribute 'job1'
(3). 对其他模块的示例
- import old_boy
- object=getattr(old_boy,"B")
- print(getattr(object,"add")(3,4)) # 第一种方式 获取 old_boy 文件中的静态方法 add
- print(getattr(old_boy.B,'add')(3,4)) # 第二种方式
- print(getattr(old_boy,'login')("alex","123")) # 调用 old_boy 文件中的 login 函数
(4). 对当前模块的示例
- import sys
- def login():
- print(55)
- def func3():
- print(333)
- content=input("<<<")
- getattr(sys.modules[__name__],content)() # 55
- getattr(sys.modules[__name__],"func3")() # 333
来源: http://www.bubuko.com/infodetail-2670103.html