PYTHON小白:第十七天

PYTHON小白:第十七天
1、 Python的动态性
Python是动态语言,动态语言的典型特征就是:类、对象的属性、方法都可以动态增加和修改。
1.1 动态属性与__slots__
前面介绍了为对象动态添加方法,但是所添加的方法只是对当前对象有效,如果希望为所有实例都添加方法,则可通过为类添加方法来实现。

运行程序时出现了TypeError: object() takes no parameters错误。发现问题是:我的构造函数的拼写错误,我写成了inti,要避免出现这种粗心的错误。

上面程序定义了Cat类,该Cat类只定义了一个构造方法,并未提供任何方法。因此,程序调用d1.walk()方法时会出现异常:Cat类并没有walk()方法。
代码为Cat动态添加了walk()方法,为类动态添加方法时不需要使用MethodType进行包装,该函数的第一个参数会自动绑定,Cat动态添加walk()方法之后,Cat类的两个实例d1、d2都具有了walk()方法,因此上面程序中最后两行d1、d2都可调用walk()方法。
Python的这种动态性固然有其优势,但给程序带来了一定的隐患:程序定义好的类,完全有可能在后面被其他程序修改,这就带来了一些不确定性。如果程序要限制为某个类动态添加属性和方法,则可通过__slots__属性来指定。
__slots__属性的值是一个元组,该元组的所有元素列出了该类的实例允许动态添加的所有属性名和方法名(对于Python而言,方法相当于属性值为函数的属性)。

上面程序中第一行粗体字代码定义了__slots__=(’walk’,’age’,’name’),这意味着程序只允许为Dog动态添加walk、age或name方法。因此上面程序为Dog对象动态添加walk()方法和age属性都是允许的,但如果程序尝试为Dog对象添加其他额外属性,程序就会引发AttributeError错误,如上面最一行代码所示。
需要说明的是,__slots__并不限制通过类来动态添加属性或方法,因此下面代码是合法的。

此外,__slots__属性指定的限制只对当前类的实例起作用,对该类派生出来的子类是不起作用。

如果要限制子类的实例动态添加属性和方法,则需要在子类中也定义__slots__属性,这样,子类的实例允许动态添加属性和方法就是子类的_slots__元组加上父类的_slots_元组的和。
1.2 使用type()函数定义类

从Python解释器的角度来看,当程序使用class定义Role类时,也可理解为定义了一个特殊的对象(type类的对象),并将该对象赋值给Role变量。因此,程序使用class定义的所有类都是type类的实例。
实际上Python完全允许使用type()函数(相当于type类的构造器函数)来创建type对象,又由于type类的实例就是类,因此Python可以使用type()函数来动态创建类。

在使用type()定义类时可指定三个参数。
 参数一:创建类名。
 参数二:该类继承的父类集合。由于Python支持多继承,因此,此处使用元组指定它的多个父类。即使实际只有一个父类,也需要使用元组语法(必须要多一个逗号)。
 参数三:该字典对象为该类绑定类变量和方法。其中字典key是类变量或方法名,如果字典的value是普通值,那就代表类变量,如果字典的value是函数,则代表方法。
从上面的输出结果可以看出,使用type()函数定义的类与直接使用class定义的类并没有任何区别。事实上Python解释器在执行使用class定义的类时,其实依然是使用type()函数来创建类。因此,无论通过哪种方式定义类,程序最终都是type实例。
1.3 使用metaclass
如果希望创建某一批类全部具有某种特征,则可通过rnetaclass来实现。使用rnetaclass可以在创建类时动态修改类定义。
为了使用metaclass动态修改类定义,程序需要先定义metaclass,metaclass应该继承type类,并重写__new__()方法。

上面程序定义了ItemMetaClass类,该类继承了type类,并重写了__new__方法,在重写该方法时为目标类动态添加了一个cal_price方法。
metaclass类的__new__方法的作用是:当程序使用class定义新类时,如果指定了metaclass,那么metaclass的new方法就会被自动执行。

上面程序定义了Book和CellPhone,在定义这两个类时都指定了metaclass信息,因此Python解释器在创建这两个类时,ItemMetaClass的_new__方法就会被调用,用于修改这两个类。
ItemMetaClass类的__new__方法会为目标类动态添加cal_price方法,因此,虽然在定义Book和CellP hone类时没有定义cal_price()方法,但这两个类依然有cal_price()方法。

通过使用metaclass可以动态修改程序中的一批类,对它们集中进行某种修改。这个功能在开发一些基础性框架时非常有用,程序可以通过使用metaclass为某一批需要具有通用功能的类添加方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值