我的Python学习笔记(四):动态添加属性和方法


声明:本文转载自https://my.oschina.net/u/3765372/blog/1605148,转载目的在于传递更多信息,仅供学习交流之用。如有侵权行为,请联系我,我会及时删除。

一、动态语言相关概念

1.1 动态语言

  • 在运行时代码可以根据某些条件改变自身结构
  • 可以在运行时引进新的函数、对象、甚至代码,可以删除已有的函数等其他结构上的变化
  • 常见的动态语言:Object-C、C#、JavaScript、PHP、Python、Erlang

1.2 动态类型语言

  • 在运行期间检查数据类型的语言
  • 数据类型不是在编译阶段决定的,而是把类型绑定延后到了运行阶段
  • 常见的动态类型语言:Python、Ruby、Erlang、JavaScript、swift、PHP、Perl

1.3 强类型语言

  • 一旦一个变量被指定了某个数据类型,如果不经过强制类型转换,那么它就永远是这个数据类型
  • 常见的强类型语言:Java、C#、Python、Object-C、Ruby

Python是动态语言,动态类型语言,也是强类型语言。所以Python可以在运行时改变自身结构,动态添加/删除属性和方法。接下来将介绍Python如何动态添加属性和方法。

 

二、动态添加属性

2.1 添加对象属性

class Person(object):     def __init__(self, newName, newAge):         self.name = newName         self.age = newAge  zhangsan = Person("张三", 18) zhangsan.addr = "北京"    # 类对象zhangsan动态添加对象属性addr print(zhangsan.name)    # 张三 print(zhangsan.age)     # 18 print(zhangsan.addr)    # 北京  lisi = Person("李四", 28) print(lisi.name)        # 李四 print(lisi.age)         # 28 print(lisi.addr)        # 'Person' object has no attribute 'addr'

由以上代码可知,Person类有两个属性:name和age。通过[对象名.属性名]给类对象zhangsan动态添加了对象属性addr,而Person的另一个类对象lisi却不能调用这个属性。

注:通过对象名添加的对象属性,只有这个对象能使用

2.2 添加类属性

class Person(object):     def __init__(self, newName, newAge):         self.name = newName         self.age = newAge  Person.addr = "北京"  # 类Person动态添加类属性addr  zhangsan = Person("张三", 18) print(zhangsan.name)    # 张三 print(zhangsan.age)     # 18 print(zhangsan.addr)    # 北京  lisi = Person("李四", 28) print(lisi.name)    # 李四 print(lisi.age)     # 28 print(lisi.addr)    # 北京

由以上代码可知,通过[类名.属性名]给类Person动态添加了类属性addr,Person的类对象zhangsan和lisi都能调用这个属性

注:通过类名添加的类属性,这个类的所有对象都能使用

 

三、动态添加方法

类中有三种方法,实例方法,静态方法和类方法,三种方法的区别如下:

  • 实例方法:需要绑定要一个对象上,第一个参数默认使用self,会把对象作为第一个参数传递进来
  • 静态方法:使用装饰器@staticmethod进行定义,类和对象都可以调用,不需要默认参数
  • 类方法:使用装饰器@classmethod进行定义,类和对象都可以调用,第一个参数默认使用cls,会把类作为第一个参数传递进来

3.1 添加实例方法

import types  class Person(object):     def __init__(self, newName, newAge):         self.name = newName         self.age = newAge      def eat(self):         print("---正在吃---")  def run(self):     print("---正在跑---")  zhangsan = Person("张三", 18) zhangsan.eat()  # ---正在吃--- zhangsan.run = types.MethodType(run, zhangsan)  # 类对象zhangsan动态添加对象方法run() zhangsan.run()  # ---正在跑---  lisi = Person("李四", 28) lisi.eat()  # ---正在吃--- lisi.run()  # 'Person' object has no attribute 'run'

由以上代码可知,Person类有一个方法:eat()方法。通过[types.MethodType(方法名, 对象名)]给类对象zhangsan动态添加了对象方法run(),同理,Person的另一个类对象lisi不能调用这个方法

注:通过对象名添加的对象方法,只有这个对象能使用

3.2 添加静态方法

class Person(object):     def __init__(self, newName, newAge):         self.name = newName         self.age = newAge      def eat(self):         print("---正在吃---")  @staticmethod def staticRun():     print("---正在跑---")  Person.staticRun = staticRun    # 类Person动态添加静态方法staticRun()  Person.staticRun()  # ---正在跑---  zhangsan = Person("张三", 18) zhangsan.eat()        # ---正在吃--- zhangsan.staticRun()  # ---正在跑---  lisi = Person("李四", 28) lisi.eat()        # ---正在吃--- lisi.staticRun()  # ---正在跑---

由以上代码可知,通过[类名.静态方法名]给类Person动态添加了静态方法staticRun(),Person类的Person的类对象zhangsan和lisi都能调用这个方法

注:通过类名添加的静态方法,这个类及这个类的所有对象都能使用

3.3 添加类方法

class Person(object):     def __init__(self, newName, newAge):         self.name = newName         self.age = newAge      def eat(self):         print("---正在吃---")  @classmethod def classRun(cls):     print("---正在跑---")  Person.classRun = classRun    # 类Person动态添加类方法classRun()  Person.classRun()  # ---正在跑---  zhangsan = Person("张三", 18) zhangsan.eat()        # ---正在吃--- zhangsan.classRun()  # ---正在跑---  lisi = Person("李四", 28) lisi.eat()        # ---正在吃--- lisi.classRun()  # ---正在跑---

由以上代码可知,通过[类名.类方法名]给类Person动态添加了类方法classRun(),Person类的Person的类对象zhangsan和lisi都能调用这个方法

注:通过类名添加的类方法,这个类及这个类的所有对象都能使用

 

四、__slots__的使用

通过以上内容,我们知道了如何动态的添加属性和方法。但是,如果我们想要限制class的属性该怎么办?例如:只允许Person实例添加name和age属性。为了达到这个目的,Python允许在定义class的时候,定义一个特殊变量__slots__来限制该class能添加的属性。

import types class Person(object):     __slots__ = ("name", "age")  # 定义__slots__         def __init__(self, newName, newAge):         self.name = newName         self.age = newAge      def eat(self):         print("---正在吃---")  def run(self):     print("---正在跑---")  Person.num = 100        # 类Person动态添加类属性num  zhangsan = Person("张三", 18) print(zhangsan.name)    # 张三 print(zhangsan.age)     # 18 print(zhangsan.num)     # 100 zhangsan.eat()          # ---正在吃---  zhangsan.addr = "北京"   # 'Person' object has no attribute 'addr' zhangsan.run = types.MethodType(run, zhangsan)  # 'Person' object has no attribute 'run'

 

通过以上代码可知,__slots__对Person类的动态添加没有限制,而Person类对象zhangsan不能再动态添加对象属性和方法。

对于__slot__有以下几个需要注意的地方:

  • __slots__只对类对象进行限制,不对类进行限制
  • __slots__不仅限制类对象的属性,还限制类对象的方法
  • __slots__仅对当前类起作用,对继承的子类不起作用
  • 在子类中定义__slots__,子类允许定义的属性就是自身的__slots__加上父类的__slots__

 

本文发表于2018年01月10日 16:32
(c)注:本文转载自https://my.oschina.net/u/3765372/blog/1605148,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。如有侵权行为,请联系我们,我们会及时删除.

阅读 1726 讨论 0 喜欢 0

抢先体验

扫码体验
趣味小程序
文字表情生成器

闪念胶囊

你要过得好哇,这样我才能恨你啊,你要是过得不好,我都不知道该恨你还是拥抱你啊。

直抵黄龙府,与诸君痛饮尔。

那时陪伴我的人啊,你们如今在何方。

不出意外的话,我们再也不会见了,祝你前程似锦。

这世界真好,吃野东西也要留出这条命来看看

快捷链接
网站地图
提交友链
Copyright © 2016 - 2021 Cion.
All Rights Reserved.
京ICP备2021004668号-1