• python动态绑定属性和方法


      基于Python 2.7.13测试。

      

      Python是动态语言,在类定义了之后,还可以动态地绑定属性和方法。

      下面先来看怎么给类的实例动态地绑定属性和方法。

    >>> class Student(object):
    ...     pass
    ...
    >>> stu1 = Student();
    >>> stu1.name = 'Tom'
    >>> print(stu1.name)
    Tom
    >>> print(dir(stu1))
    ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribut
    e__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_e
    x__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_
    _weakref__', 'name']
    >>>
    >>> def set_age(self, age):
    ...     self.age = age
    ...
    >>> set_age(stu1, 20)
    >>> print(stu1.age)
    20
    >>> print(dir(stu1))
    ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribut
    e__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_e
    x__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_
    _weakref__', 'age', 'name']
    >>> #并没有绑定方法到实例上
    ...
    >>> from types import MethodType
    >>> stu1.set_age = MethodType(set_age, stu1)
    >>> stu1.set_age(33)
    >>> print(stu1.age)
    33
    >>> print(dir(stu1))
    ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribut
    e__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_e
    x__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_
    _weakref__', 'age', 'name', 'set_age']
    >>> #绑定的属性和方法只属于stu1的,对于其他实例不起作用
    ...
    >>> stu2 = Student()
    >>> print(dir(stu2))
    ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribut
    e__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_e
    x__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_
    _weakref__']

       看怎么给类动态地绑定属性和方法。

    >>> class Student(object):
    ...     pass
    ...
    >>> def set_name(self, name):
    ...     self.name = name
    ...
    >>> from types import MethodType
    >>> Student.set_name = MethodType(set_name, Student)
    >>> print(dir(Student))
    ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribut
    e__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_e
    x__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_
    _weakref__', 'set_name']
    >>> stu1 = Student()
    >>> stu1.set_name('Rose')
    >>> stu2 = Student()
    >>> stu2.set_name('Jack')
    >>> print(stu1.name)
    Jack
    >>> print(stu2.name)
    Jack
    >>> ########
    >>> class Student(object):
    ...     pass
    ...
    >>> def set_name(self, name):
    ...     self.name = name
    ...
    >>> Student.set_name = set_name
    >>> print(dir(Student))
    ['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribut
    e__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_e
    x__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_
    _weakref__', 'set_name']
    >>> stu1 = Student()
    >>> stu1.set_name('Rose')
    >>> stu2 = Student()
    >>> stu2.set_name('Jack')
    >>> print(stu1.name)
    Rose
    >>> print(stu2.name)
    Jack

      想要限制实例属性,只允许对Student实例添加name和age属性。__slots__变量,来限制该class实例能添加的属性。

    >>> class Student(object):
    ...     __slots__ = ('name', 'age')
    ...
    >>> stu1 = Student()
    >>> stu1.name = 'John'
    >>> stu1.addr = 'Beijing'
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'Student' object has no attribute 'addr'

      __slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用。

    >>> class MidStudent(Student):
    ...     pass
    ...
    >>> stu2 = MidStudent()
    >>> stu2.addr = 'Beijing'
    >>> print(stu2.addr)
    Beijing

      slots只能限制添加属性,不能限制通过添加方法来添加属性。

    >>> from types import MethodType
    >>>
    >>> class School(object):
    ...     __slots__ = ('name')
    ...
    >>> def set_city(self, city):
    ...     self.city = city
    ...
    >>> School.set_city = MethodType(set_city, School)
    >>>
    >>> sch = School()
    >>> sch.set_city('BeiJing')
    >>> print(sch.city)
    BeiJing

      Python创建class的方法就是使用type()函数。 type()函数既可以返回一个对象的类型,又可以创建出新的类型。

    >>> def fun(self, name='World'):
    ...     print('Hello %s' % name)
    ...
    >>> #创建Hello类
    ... Hello = type('Hello', (object,), dict(hello=fun))
    >>>
    >>> h = Hello()
    >>> h.hello()
    Hello World

      要创建一个class对象,type()函数依次传入3个参数:

    1. class的名称。
    2. 继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法。
    3. class的方法名称与函数绑定,这里我们把函数fn绑定到方法名hello上。

      通过type()函数创建的类和直接写class是完全一样的,因为Python解释器遇到class定义时,仅仅是扫描一下class定义的语法,然后调用type()函数创建出class。 

  • 相关阅读:
    JavaScript 弹窗
    创建对象构造器
    DOM事件
    document对象“还在更新”
    JavaScript 闭包
    使用 "use strict" 指令
    constructor 属性
    2019暑期集训第一周小结
    无向图求割边
    矩阵快速幂
  • 原文地址:https://www.cnblogs.com/lnlvinso/p/8999834.html
Copyright © 2020-2023  润新知