网站运营建设的培训/杭州网站优化体验
1.属性属性定义:python中属性其实是普通方法的衍生属性操作:用@property装饰器操作类属性用类或实例直接操作类属性obj.name,obj.age=18,del obj.age用python内置函数操作属性属性意义:访问属性时类似访问字段象,属性由方法衍生而来,如Python没有属性,方法完全可代替其功能可动态获取属性值,应用更灵活;可制定属性规则,防随意修改属性值属性函数:hasattr(object, name) #判断是否包含指定的属性或方法getattr(object, name[,default]) #获取对象属性或方法;无抛AttributeErrorsetattr(object, name, values) #对象属性赋值(修改或创建)delattr(obj, name): #删除属性无抛AttributeError,无返回值type.__dict__ #类属性-类实例变量dir #返回当前范围的所有属性名称列表内置属性:__dict__ : #获取类所有信息返回字典{属性:属性值}__doc__ : #类文档字符串__name__: #类名__module__: #类定义所在模块 当前模块返回’__main__’__bases__ : #类所有父类元组 property():语法:property(fget=None, fset=None, fdel=None, doc=None) -> property attribute说明:fget 获取属性值方法fset 设置属性值方法fdel 删除属性值方法doc 属性描述信息;如省略,会把 fget 方法的docstring 拿来用(如果有话) 注意:类名.属性.__doc__ #查看属性文档字符串Student.age.__doc__属性装饰器:用途:把方法包装成属性;在获取,设置,删除属性时需额外做一些工作实现getter,setter,deleter功能,对属性的取值和赋值加以控制,提高代码的稳定性@property 语法糖提供比 property() 函数更简洁直观写法格式:@property 获取属性值的方法,被装饰方法的名字会被用做 属性名def func(self):仅有一个self参数,调用时无需括号@属性名.setter 装饰的方法是设置属性值的方法@属性名.deleter 装饰的方法是删除属性值的方法注意:描述符只对实例方法有效,对于静态方法、类方法都无法使用不能通过在__init__()和其他方法中创建描述符对象来为每个实例创建描述符
2.实例:属性操作实例1:#用类或实例直接操作类属性#实例.属性; 类.属性 对类的属性没有操作控制规则,容易被修改
class Student:total = 10def __init__(self,name='Tom',age=22):self.name = nameself.age=agedef view(self):print(self.name,self.age)def add(self,x,y):return x+y#属性操作:查看赋值删除
s=Student()
hasattr(s, 'age')# Trues.age # 等价:getattr(s,'age') 查找属性调用obj.__getattrribute__(‘name’)
del s.age # 等价:delattr(s,'age') 删除属性调用obj.__delattr__(‘name’)
s.age=20 # 等价:setattr(s,'age',20) 设置属性调用obj.__setattr__(‘name’,value)
实例2:内置函数操作属性
getattr(s,'age')
delattr(s,'age')
setattr(s,'age',20)
实例3:属性装饰器实例3.1:
class Person(object):def __init__(self):self._age=Nonedef get_age(self): return self.agedef set_age(self, value):if value <= 0 or value > 200:raise ValueError('age must between 0 ~ 200!')self.age = values = Person()
s.set_age(30);print(s.get_age(),end=',')
del s.age;print(hasattr(s, 'age')) # 30,False
实例3.2:
class Person(): #新式类def __init__(self):self._age=None@property #getter方法变成属性@property等同age = property(fget=age)def age(self):return self._age@age.setter #把一个setter方法变成属性赋值def age(self, value):if value <=0 or value > 200:raise ValueError('age must between 0 ~ 200!')self._age = value@age.deleter # 删除属性def age(self):del self._ages = Person()
s.age = 30 # 实际转化为s.set_age(60)
print(s.age,end=',') # 实际转化为s.get_age()
del s.age;print(hasattr(s, 'age')) # 30,False
实例3.3:#旧版定义-不建议使用直接用@property
class Person(object):def __init__(self):self._age=Nonedef get_age(self):return self._agedef set_age(self,value):if value <=0 or value > 200:raise ValueError('age must between 0 ~ 200!')self._age=valuedef del_age(self):del self._age# raise TypeError("Can't delete age")age=property(get_age,set_age,del_age,'文档')#增加property类s = Person()
s.age = 30;print(s.age,end=',')
del s.age;print(hasattr(s, 'age')) # 30,False
实例4:#查看类属性s.__dict__ # {'name': 'Tom', 'age': 20} 类实例变量
s.__dict__['id']=1020120 # 对实例的修改反应到局部__dict__属性中
s.__dict__ # {'name': 'Tom', 'age': 20, 'id': 1020120}s.__class__ # <class '__main__.Student'># __dict__ 获取属性列表:
Student.__dict__.keys() # dict_keys(['__module__', 'total', '__init__', 'view', 'add', '__dict__', '__weakref__', '__doc__']) s.__dir__() # 等价dir(s) ['name','age','id','total', 'view','add',...]
dir(Student) # [ 'add', 'total','view',...]
Student.__dir__(Student) # [ 'mro',...]# 使用 inspect 包功能来过滤:
import inspect#获取属性
[i for i in dir(s) if not callable(getattr(s, i)) and i[0]!='_']# ['age', 'id', 'name', 'total']#获取内置函数
[i for i in dir(s) if inspect.isbuiltin(getattr(s, i))] # ['__dir__','__format__',...]# 获取函数:
[i for i in dir(s) if inspect.isfunction(getattr(s, i))] # []# 获取可调用对象:
[i for i in dir(s) if inspect.isroutine(getattr(s, i)) and i[0]!='_']# ['add', 'view']
实例5:备注实例5.1:特性的继承--不建议使用实例5.1.1:完全重写父类property
#在子类中重新定义一个同名getter函数,再加上@propety装饰器即可
class Student(Person):def __init__(self):self._age=None@propertydef age(self):return self.age
实例5.2.2:重写父类property的某些方法
class Girl(Person):def __init__(self):self._age=None@propertydef age(self):return super().age@age.setterdef age(self, value):super(Girl, Girl).age.__set__(self, value)
实例5.2:
class PropertyTyped (object):#不建议使用-直接用@property'''定义一个描述符分配属性进行类型检查,如果尝试删除属性,它将引发错误'''def __init__( self, name,type, default=None):self.name='_'+nameself.type=typeself.default=default if default else type()def __get__(self,instance,cls):return getattr (instance, self.name, self. default)def __set__(self,instance, value):if not isinstance (value,self.type):raise TypeError("Must be a%s"% self.type)setattr (instance, self.name, value)def __delete__(self, instance):raise AttributeError ( "Can't delete attribute" )class Boy (object):name=PropertyTyped("name", str)num=PropertyTyped ("num", int, 42)b= Boy()
a= b.name #隐式调用Boy.name.__get__(f,Foo)
b.name="Tom" #调用Boy.name.__ set__(f, "Tom")
del b.name #调用Boy.name.__delete__(f)
实例5.3:#纯Python等效项property():
class Property(object):"Emulate PyProperty_Type() in Objects/descrobject.c"def __init__(self, fget=None, fset=None, fdel=None, doc=None):self.fget = fgetself.fset = fsetself.fdel = fdelif doc is None and fget is not None:doc = fget.__doc__self.__doc__ = docdef __get__(self, obj, objtype=None):if obj is None:return selfif self.fget is None:raise AttributeError("unreadable attribute")return self.fget(obj)def __set__(self, obj, value):if self.fset is None:raise AttributeError("can't set attribute")self.fset(obj, value)def __delete__(self, obj):if self.fdel is None:raise AttributeError("can't delete attribute")self.fdel(obj)def getter(self, fget):return type(self)(fget, self.fset, self.fdel, self.__doc__)def setter(self, fset):return type(self)(self.fget, fset, self.fdel, self.__doc__)def deleter(self, fdel):return type(self)(self.fget, self.fset, fdel, self.__doc__)