一、动态语言相关概念

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. java web 学习笔记 jsp内置对象

    jsp2 表达式语言的内置对象 使用方式${object.attributename} 或者${object["attributename"]} pageContext pageS ...

  2. Android 防内存泄露handler

    Android 防内存泄露handler 1.使用弱引用 WeakRefHander /** * 作者: allen on 15/11/24.感谢开源作者https://coding.net/u/co ...

  3. SDL2源码分析2:窗体(SDL_Window)

    ===================================================== SDL源码分析系列文章列表: SDL2源码分析1:初始化(SDL_Init()) SDL2源 ...

  4. TempData知多少

    网上对TempData的总结为: 保存在session中,Controller每次执行请求时,会从session中一次获取所有tempdata数据,保存在单独的内部数据字典中,而后从session中清 ...

  5. shell 参数记录

    $0  执行脚本的名称 $* 和 $@ 所有参数 $#  参数个数 $_  上个命令的最后一个参数 $$  代表当前命令所在的pid $!  代表最后执行的 '后台' 命令的pid $? 代表上条命令 ...

  6. 【JavaScript】 JS面向对象的模式与实践 (重点整治原型这个熊孩子 (/= _ =)/~┴┴ )

    参考书籍 <JavaScript高级语言程序设计>—— Nicholas C.Zakas <你不知道的JavaScript>  —— KYLE SIMPSON   在JS的面向 ...

  7. springboot整合redis

    springboot-整合redis   springboot学习笔记-4 整合Druid数据源和使用@Cache简化redis配置 一.整合Druid数据源 Druid是一个关系型数据库连接池,是阿 ...

  8. 《Netty5.0架构剖析和源码解读》【PDF】下载

    <Netty5.0架构剖析和源码解读>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230062545 内容简介 Netty 是个异步的 ...

  9. php--php调java接口验签

    <?php namespace Fmall_cloud\Model; use Think\Model; class DealJavaModel extends Model { /** * @ti ...

  10. js验证input输入框(字母,数字,符号,中文)

    [javascript]代码库 <h1>js验证输入框内容</h1> <br /> <br /> 只能输入英文 <input type=" ...