一、动态语言相关概念

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) #
print(zhangsan.addr) # 北京 lisi = Person("李四", 28)
print(lisi.name) # 李四
print(lisi.age) #
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) #
print(zhangsan.addr) # 北京 lisi = Person("李四", 28)
print(lisi.name) # 李四
print(lisi.age) #
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) #
print(zhangsan.num) #
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__

我的Python学习笔记(四):动态添加属性和方法的更多相关文章

  1. python学习笔记8--面向对象--属性和方法详解

    属性: 公有属性  (属于类,每个类一份) 普通属性  (属于对象,每个对象一份) 私有属性    (属于对象,跟普通属性相似,只是不能通过对象直接访问) 方法:(按作用) 构造方法 析构函数 方法: ...

  2. day_5.26python动态添加属性和方法

    python动态添加属性和方法 既然给类添加⽅法,是使⽤ 类名.⽅法名 = xxxx ,那么给对象添加⼀个⽅法 也是类似的 对象.⽅法名 = xxx '''2018-5-26 13:40:09pyth ...

  3. js对象动态添加属性,方法

    1. 动态添加属性,方法 var object = new Object(); object.name = "name"; object.age = 19; >>> ...

  4. Python学习笔记四:面向对象编程

    一:定义类并创建实例 Python中定义类,通过class关键字,类名开头大写,参数列表为所继承的父类.如果没有需要明确继承的类,则继承object. 使用类来创建对象,只需 类名+() 形式即可,p ...

  5. Python笔记_第三篇_面向对象_8.对象属性和类属性及其动态添加属性和方法

    1. 对象属性和类属性. 我们之前接触到,在类中,我们一般都是通过构造函数的方式去写一些类的相关属性.在第一次介绍类的时候我们把一些属性写到构造函数外面并没有用到构造函数,其实当时在写的时候,就是在给 ...

  6. python动态添加属性和方法

    ---恢复内容开始--- python动态添加属性: class Person(object): def __init__(self,newName,newAge): self.name = newN ...

  7. python 动态添加属性及方法及“__slots__的作用”

    1.动态添加属性 class Person(object): def __init__(self, newName, newAge): self.name = newName self.age = n ...

  8. Python基础之动态添加属性,方法,动态类,静态类

    ## 动态添加属性class Person: def __init__(self,name): self.name = name# 1.通过对象.属性名称来操作p = Person('KTModel' ...

  9. JS内置对象的原型不能重定义?只能动态添加属性或方法?

    昨天马上就快下班了,坐在我对面的同事突然问我一个问题,我说“爱过”,哈哈,开个玩笑.情况是这样的,他发现JS的内置对象的原型好像不能通过字面量对象的形式进行覆盖, 只能动态的为内置对象的原型添加属性或 ...

随机推荐

  1. 高效管理http连接

    1.Http连接基础 Http协议承载了互联网上的主要流量,然而说到传输,还要回归到最基本的网络分层模型TCP/IP.TCP/IP是全球计算机及网络设备都在使用的一种常用的分组交互网络分层协议集.客户 ...

  2. java学习笔记IO之File类

    File类总结 p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Times } p.p2 { margin: 0.0px 0.0px 0.0p ...

  3. js图片懒加载(滚动加载)是否生效

    一.什么是懒加载? 对未出现在视野范围内的图片先不进行加载,等到出现在视野范围才去加载. 二.为什么使用懒加载? 懒加载的主要目的是作为服务器前端的优化,减少请求数或延迟请求数. 理论性知识大家都有自 ...

  4. Best time to buy and sell stocks IV

    题目 https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/ Say you have an array for which ...

  5. ASP.NET Core 使用 Alipay.AopSdk.Core 常见问题解答

    1.Alipay.AopSdk.Core.AopException:"您使用的私钥格式错误,请检查RSA私钥配置,charset = UTF-8" 出现这个问题,就是配置不正确.首 ...

  6. MongoDB 数据库备份与恢复

    1.MongoDB数据库备份     1.语法:         mongodump -h dbhost -d dbname -o dbdirectory         参数说明:         ...

  7. android 事件传递机制(1)

    在项目中,经常遇到事件冲突,ScrollView,ViewPager滑动卡顿等情况,比如:onClick和onLongClick事件冲突,dispatchTouchEvent,onInterceptT ...

  8. jdk动态代理举例

    JDK动态代理是基于接口的代理,下面举例说明 代理类:proxy,代理动作必须要基于一个proxy实例来执行 代理执行类:实现InvocationHandler,案例中是TestInvocationH ...

  9. WebAPI返回JSON

    web api写api接口时默认返回的是把你的对象序列化后以XML形式返回,那么怎样才能让其返回为json呢,下面就介绍两种方法: 方法一:(改配置法) 找到Global.asax文件,在Applic ...

  10. 【ANT】description元素和属性

    <?xml version="1.0" ?> <project default="test"> <description> ...