python--基础知识点--动态添加属性和方法

一、动态语言相关概念

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__的使用

在 Python 中,slots 是一个特殊的属性,用于限制一个类实例的属性。通过定义 slots,你可以告诉 Python 只允许实例化对象具有指定的属性,而不允许动态地添加新的属性。

使用 slots 有以下几个作用:

节省内存:由于 slots 限制了实例可以拥有的属性,它会使得每个实例占用的内存更小。
提高访问速度:由于实例中的属性是固定的,Python 不需要使用字典来存储对象的属性,因此可以提高属性访问的速度。
防止错误的属性赋值:如果尝试给 slots 中未列出的属性赋值,Python 会抛出 AttributeError,从而避免一些错误。
例如,以下是一个使用 slots 的简单示例:

class Point:
    __slots__ = ('x', 'y')
    
    def __init__(self, x, y):
        self.x = x
        self.y = y

# 创建 Point 对象
p = Point(10, 20)

# 由于 __slots__ 中只包含 'x' 和 'y',因此以下代码将会抛出 AttributeError
p.z = 30  # AttributeError: 'Point' object has no attribute 'z'

需要注意的是,使用 slots 也有一些限制,例如不能再动态地给实例添加新的属性,且子类默认不会继承父类的 slots。因此,在使用 slots 时需要谨慎考虑其影响。

转载博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值