zoukankan      html  css  js  c++  java
  • __slots__ 和 @property

     动态非常灵活, 创建一个class后, 给实例绑定一个属性:

    >>> class Bird:
    ...     pass
    ...
    >>> s = Bird()
    >>> s.name = 'bob'
    >>> s.name
    bob

    也可以给实例绑定一个方法, 但是这对另一个实例是无效的: 

    >>> def age(self,age):
    ...     self.age = age
    ... 
    >>> from types import MethodType
    >>> 
    >>> s.age = MethodType(age,s,Bird)
    >>> s.age(0.5)
    >>> print s.age
    0.5
    
    >>> s2 = Bird()
    >>> s2.age(1)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: Bird instance has no attribute 'age'

    为了给所有实例都绑定方法,可以给class绑定方法, 绑定后所以属于该类的实例均可调用:

    >>> def is_running(self):
    ...     print 'running...'
    ... 
    >>> Bird.is_running = MethodType(is_running, None, Bird)
    >>> s3 = Bird()
    >>> s3.is_running()
    running...
    >>> s2.is_running()
    running...

     __slots__


    如果我们需要限制class的属性怎么办? 比如说我们定义一个Person类, 只允许对Person实例添加 name age属性, 不允许添加gender属性! 所以我们需要使用 __slots__

    >>> class Person(object):
    ...     __slots__ = ('name','age')
    ... 
    >>> s = Person()
    >>> s.name = 'Johb'
    >>> s.age = '22'
    >>> s.gender = 'male'
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'Person' object has no attribute 'gender'

    但是对于Person的子类是不起作用的, 除非子类也定义 __slots__

    >>> class SuperPerson(Person):
    ...     pass
    ... 
    >>> s = SuperPerson()
    >>> s.aaaaa = 'no restriction'
    >>> s.aaaaa
    'no restriction'

    注意: 因为Python的历史遗留问题, 在2.x版本中, 如果类后面没有跟object ,  __slots__的限制将会无效

    >>> class Person:
    ...     __slots__=('name','age')
    ... 
    >>> s.gender = 'male'
    >>> s.gender
    'male'

    @property


    如果不对age做限制,我们可以任意设置age的值, 显然这是不规范的. 

    >>> s.age = 99999999
    >>> s.age = 'aaaaaa'

    当然我们可以麻烦一点, 设置两个函数:

    class Person(object):
        def get_age(self):
            return self.age
        def set_age(self,value):
            if not isinstance(value, int):
                raise ValueError('Age must be an integer')
            if value < 0 or value > 100:
                raise ValueError('Age must between 0 ~ 100')
            self.age = value
    >>> s = Person()
    >>> s.set_age(22)
    >>> se.get_age()
    >>> 22 >>> s.set_age(11111) Traceback (most recent call last): ................................. ValueError: Age must between 0 ~ 100

    使用更简单的方法@property, 把一个getter方法变成属性,只需要加上@property就可以了,此时,@property本身又创建了另一个装饰器@age.setter,负责把一个setter方法变成属性赋值. 

    class Person(object):
        @property
        def age(self):
            return self.age
    
        @age.setter
        def age(self, value):
            if not isinstance(value, int):
                raise ValueError('age must be an integer!')
            if value < 0 or value > 100:
                raise ValueError('age must between 0~100')
            self.age = value
    
    >>>s = Person()
    >>>s.age = 40
    >>>s.age
    40
    >>>s.age = 11111
    Traceback (most recent call last):
    .................................
    ValueError: Age must between 0 ~ 100
  • 相关阅读:
    Django contenttypes组件
    Django admin组件使用
    Django 信号
    Django 中间件
    Django 分页组件替换自定义分页
    Django ORM操作补充
    Django ORM 操作2 增删改
    Django 序列化
    JavaScript
    CSS 属性
  • 原文地址:https://www.cnblogs.com/zhanhg/p/4395895.html
Copyright © 2011-2022 走看看