zoukankan      html  css  js  c++  java
  • python笔记57-@property源码解读与使用

    前言

    Python 内置的 @property 装饰器的作用是把方法变成属性,调用的时候不需要加括号

    property源码

    property() 方法的传四个参数

    • fget --获取属性值的函数
    • fset --设置属性值的函数
    • fdel --删除属性值函数
    • doc --属性描述信息
    class property(object):
        """
        property(fget=None, fset=None, fdel=None, doc=None) -> property attribute
        
        fget is a function to be used for getting an attribute value, and likewise
        fset is a function for setting, and fdel a function for del'ing, an
        attribute.  Typical use is to define a managed attribute x:
        
        class C(object):
            def getx(self): return self._x
            def setx(self, value): self._x = value
            def delx(self): del self._x
            x = property(getx, setx, delx, "I'm the 'x' property.")
        
        Decorators make defining new properties or modifying existing ones easy:
        
        class C(object):
            @property
            def x(self):
                "I am the 'x' property."
                return self._x
            @x.setter
            def x(self, value):
                self._x = value
            @x.deleter
            def x(self):
                del self._x
        """
        def deleter(self, *args, **kwargs): # real signature unknown
            """ Descriptor to change the deleter on a property. """
            pass
    
        def getter(self, *args, **kwargs): # real signature unknown
            """ Descriptor to change the getter on a property. """
            pass
    
        def setter(self, *args, **kwargs): # real signature unknown
            """ Descriptor to change the setter on a property. """
            pass
    
        def __delete__(self, *args, **kwargs): # real signature unknown
            """ Delete an attribute of instance. """
            pass
    
        def __getattribute__(self, *args, **kwargs): # real signature unknown
            """ Return getattr(self, name). """
            pass
    
        def __get__(self, *args, **kwargs): # real signature unknown
            """ Return an attribute of instance, which is of type owner. """
            pass
    
        def __init__(self, fget=None, fset=None, fdel=None, doc=None): # known special case of property.__init__
            """
            property(fget=None, fset=None, fdel=None, doc=None) -> property attribute
            
            fget is a function to be used for getting an attribute value, and likewise
            fset is a function for setting, and fdel a function for del'ing, an
            attribute.  Typical use is to define a managed attribute x:
            
            class C(object):
                def getx(self): return self._x
                def setx(self, value): self._x = value
                def delx(self): del self._x
                x = property(getx, setx, delx, "I'm the 'x' property.")
            
            Decorators make defining new properties or modifying existing ones easy:
            
            class C(object):
                @property
                def x(self):
                    "I am the 'x' property."
                    return self._x
                @x.setter
                def x(self, value):
                    self._x = value
                @x.deleter
                def x(self):
                    del self._x
            
            # (copied from class doc)
            """
            pass
    
        @staticmethod # known case of __new__
        def __new__(*args, **kwargs): # real signature unknown
            """ Create and return a new object.  See help(type) for accurate signature. """
            pass
    
        def __set__(self, *args, **kwargs): # real signature unknown
            """ Set an attribute of instance to value. """
            pass
    
        fdel = property(lambda self: object(), lambda self, v: None, lambda self: None)  # default
    
        fget = property(lambda self: object(), lambda self, v: None, lambda self: None)  # default
    
        fset = property(lambda self: object(), lambda self, v: None, lambda self: None)  # default
    
        __isabstractmethod__ = property(lambda self: object(), lambda self, v: None, lambda self: None)  # default
    

    源码解读

    先看源码里面第一个示例

    class C(object):
    
        def getx(self):
            return self._x
    
        def setx(self, value):
            self._x = value
    
        def delx(self):
            del self._x
    
        x = property(getx, setx, delx, "I'm the 'x' property.")
    

    实例化后调用x属性

    c = C()
    c.x = 20     # c.x = value 将触发 setter
    print(c.x)   # c.x 将触发 getter
    del c.x      # del c.x 触发 deleter
    

    c 是 C 的实例化对象, c.x 将触发 getter,c.x = value 将触发 setter , del c.x 触发 deleter。
    如果给定 doc 参数,其将成为这个属性值的 docstring,否则 property 函数就会复制 fget 函数的 docstring(如果有的话)

    装饰器使定义新属性或修改现有属性变得容易,property 的 getter, setter 和 deleter 方法同样可以用作装饰器:

    class C(object):
        def __init__(self):
            self._x = None
     
        @property
        def x(self):
            """I'm the 'x' property."""
            return self._x
     
        @x.setter
        def x(self, value):
            self._x = value
     
        @x.deleter
        def x(self):
            del self._x
    

    这个代码和第一个例子完全相同,但要注意这些额外函数的名字和 property 下的一样,例如这里的 x。

    @property 只读属性

    我们知道类的属性是可以动态赋值的

    class People(object):
    
        def __init__(self):
            self.name = "yoyo"
            self.age = 20
    
    people = People()
    print(people.age)   # 20
    # 属性动态赋值
    people.age = 22
    print(people.age)   # 22
    

    如果我不想让age属性改变,可以使用 @property 可以设置只读属性的 getter 方法

    class People(object):
    
        def __init__(self):
            self.name = "yoyo"
            self.age = 20
    
        @property
        def get_age(self):
            return 20
    
    
    people = People()
    print(people.get_age)   # 20
    

    如果使用这种赋值代码people.get_age = 22,会抛出异常AttributeError: can't set attribute

    使用示例

    设置 my_age 属性可读可写

    class Person(object):
        def __init__(self, name, age):
            self.__name = name
            self.__age = age
    
        @property
        def my_age(self):
            return self.__age
    
        @my_age.setter
        def my_age(self, value):
            """设置my_age属性,并校验值"""
            if not isinstance(value, int):
                raise ValueError('年龄必须是数字!')
            if value < 0 or value > 100:
                raise ValueError('年龄必须是0-100')
            self.__age = value
    
    
    person = Person("yoyo", 20)
    print(person.my_age)  # 20
    person.my_age = 22
    print(person.my_age)  # 22
    person.my_age = "hh"  # ValueError: 年龄必须是数字!
    

    如果你想设置my_age属性可以删除,需用到property 的 deleter 装饰器

  • 相关阅读:
    IEE754算法
    EQ控制卡二次开发(火凤凰、蓝精灵异步单双色控制卡卡)
    康耐德C2000开关量采集
    初次了解MVC框架模式
    jQuery常用事件
    jQuery做一个小小的移动图片的位置
    jQuery关于复选框的基本小功能
    WebRequest类: WebRequest类是.NET.Framework的请求/响应模型的抽象基类,用于访问Internet数据
    .net与三层的异同
    mvc基础
  • 原文地址:https://www.cnblogs.com/yoyoketang/p/14924559.html
Copyright © 2011-2022 走看看