python类属性@property(全) tcy

1.属性

属性定义:
    python中属性其实是普通方法的衍生

属性操作:
    用@property装饰器操作类属性
    用类或实例直接操作类属性obj.name,obj.age=18,del obj.age
    用python内置函数操作属性

属性意义:
    访问属性时类似访问字段象,属性由方法衍生而来,如Python没有属性,方法完全可代替其功能
    可动态获取属性值,应用更灵活;可制定属性规则,防随意修改属性值

属性函数:
    hasattr(object, name)                #判断是否包含指定的属性或方法
    getattr(object, name[,default])    #获取对象属性或方法;无抛AttributeError
    setattr(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 = 10
    def __init__(self,name='Tom',age=22):
        self.name = name
        self.age=age
  
    def view(self):
        print(self.name,self.age)
        
    def add(self,x,y):
        return x+y
    
#属性操作:查看赋值删除    
s=Student()
hasattr(s, 'age')# True

s.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=None
        
    def get_age(self):    
        return self.age
        
    def set_age(self, value):
       if value <= 0 or value > 200:raise ValueError('age must between 0 ~ 200!')
       self.age = value
    
s = 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._age
        
s = 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=None
        
    def get_age(self):
       return self._age
       
    def set_age(self,value):
       if value <=0 or value > 200:raise ValueError('age must between 0 ~ 200!')
       self._age=value
       
    def 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__                    # 

# __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
        
    @property
    def age(self):
        return self.age
实例5.2.2:重写父类property的某些方法
class Girl(Person):
    def __init__(self):
        self._age=None
        
    @property
    def age(self):
        return super().age
        
    @age.setter
    def 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='_'+name
        self.type=type
        self.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 = fget
        self.fset = fset
        self.fdel = fdel
        if doc is None and fget is not None:
            doc = fget.__doc__
        self.__doc__ = doc
    
    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        if 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__)

你可能感兴趣的:(python)