一、property
property是一个装饰器函数
装饰器函数的使用方法:在函数、方法、类的上面一行直接@装饰器的名字
装饰器的分类:
1、装饰函数
2、装饰方法:property
3、装饰类
import math class Circle: def __init__(self,radius): #圆的半径radius self.radius=radius @property def area(self): return math.pi * self.radius**2 #计算面积 @property def perimeter(self): return 2*math.pi*self.radius #计算周长 c=Circle(10) print(c.radius) print(c.area) #可以向访问数据属性一样去访问area,会触发一个函数的执行,动态计算出一个值 print(c.perimeter) #同上 ''' 输出结果: 314.1592653589793 62.83185307179586 '''
为什么要用property
将一个类的函数定义成特性以后,对象再去使用的时候c.area,根本无法察觉自己的area是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则
class Student: def __init__(self,name): self.__name = name @property # 把方法伪装成属性 def name(self): return self.__name @name.setter # 用setter装饰一个跟property同名的方法 def name(self,new): if type(new) is str: self.__name = new obj = Student('小明') print(obj.name) # 小明 obj.name = '小红' # 赋值的时候,就触发被setter装饰器装饰的方法 print(obj.name) # 小红 # 好处:用来保护一个变量,在修改的时候能够添加一些保护条件
class Goods: __discount = 0.8 # 全场8折 def __init__(self,price): self.__price = price # 商品原价 @property def price(self): return Goods.__discount * self.__price # 折后价 @price.setter def price(self,new): self.__price = new # 更改原价 @price.deleter def price(self): del self.__price # 删除商品价格 apple = Goods(10) print(apple.price) # 8.0 apple.price = 8 # 重新赋值 print(apple.price) # 6.4 del apple.price # 删除属性 # 一个方法被伪装成属性后 # 应该可以执行一个属性的增删改查操作 # 那么增加和修改,就对应这setter装饰的方法:这个方法有一个必传的参数new,表示赋值的时候等号后面的值 # 删除一个属性,对应着被deleter装饰的方法,这个方法并不能在执行的时候真的删除这个属性,而是你在代码中执行什么就有什么效果 class A: def __init__(self): self.__f = open('aaa','w') @property def f(self): return self.__f @f.deleter def f(self): self.__f.close() # 删除一个文件,要先关闭文件 del self.__f
二、classmethod
在类中定义一个类方法、是一个装饰器
什么时候用?
如果你的整个方法中都没有用到对象命名空间中的名字,且你用到了类的命名空间中的名字(普通方法和property方法除外)
类方法的默认参数:cls指的是调用这个方法的类
类方法的调用方式:通过类名调用,本质是方法
类方法的特点:
只使用类中的资源,且这个资源可以直接用类名引用的使用,那这个方法应该被改成一个类方法
静态属性
普通方法
类方法
property方法
class Goods: __discount = 0.8 # 静态属性(全场8折) def __init__(self,price): self.__price = price # 对象属性 self.name = 'apple' @property def price(self): print(self) return self.__price * Goods.__discount # 折后价 @classmethod def change_discount(cls,new): # 类方法 cls.__discount = new # Goods.change_discount(0.7) # 把折扣价改成7折 # print(Goods.__dict__) ''' {'__module__': '__main__', '_Goods__discount': 0.7, '__init__': <function Goods.__init__ at 0x01688DB0>, 'price': <property object at 0x01693A50>, 'change_discount': <classmethod object at 0x0160E0F0>, '__dict__': <attribute '__dict__' of 'Goods' objects>, '__weakref__': <attribute '__weakref__' of 'Goods' objects>, '__doc__': None} ''' apple = Goods(10) banana = Goods(20) apple.change_discount(0.7) # 把折扣价改成7折 print(apple.price) # 7 print(banana.price) # 14
# 类: # 静态属性 类 所有的对象都统一拥有的属性 # 类方法 类 如果这个方法涉及到操作静态属性、类方法、静态方法 cls 表示类 # 静态方法 类 普通方法,不使用类中的命名空间也不使用对象的命名空间 : 一个普通的函数 没有默认参数 # 方法 对象 self 表示对象 # property 对象 self 表示对象
三、staticmethod
将一个普通的函数放到类中来就给这个函数加上一个@staticmethod装饰器
这个函数就不需要传默认的参数:self,cls
静态方法的调用方式:通过类名调用,本质还是函数
class Staticmethod_Demo(): role = 'dog' @staticmethod def func(): print("当普通方法用") Staticmethod_Demo.func()
class Foo: @classmethod def class_method(cls):pass @staticmethod def static_method():pass from types import MethodType,FunctionType obj = Foo() print(isinstance(Foo.class_method,MethodType)) # True 判断它是否一个方法 print(isinstance(Foo.static_method,FunctionType)) # True 判断它是否一个函数 print(obj.class_method) # <bound method Foo.class_method of <class '__main__.Foo'>> print(obj.static_method) # <function Foo.static_method at 0x013A8DB0>
四、isinstance
检测对象与类之间的关系
print(type(123) is int) # True print(isinstance(123,int)) # True class A: pass class B(A): pass a = A() b = B() print(type(a) is A) # True print(type(a) is B) # False print(type(b) is A) # False print(type(b) is B) # True print(isinstance(a,A)) # True print(isinstance(b,A)) # True print(isinstance(a,B)) # False print(isinstance(b,B)) # True # isinstance就是检测对象与类之间的关系
五、issubclass
检测类与类之间的关系
class A: pass class B(A): pass print(issubclass(A,B)) # False print(issubclass(B,A)) # True # issubclass就是检测类与类之间的关系