面向对象高级编程:使用__slots__

简介:

正常情况下,当我们定义了一个class,创建了一个class的实例后,我们可以给该实例绑定任何属性和方法,这就是动态语言的灵活性。先定义class:

class Student(object):
    pass

然后,尝试给实例绑定一个属性:

>>> s = Student()
>>> s.name = 'Michael' # 动态给实例绑定一个属性
>>> print(s.name)
Michael

还可以尝试给实例绑定一个方法:

>>> def set_age(self, age): # 定义一个函数作为实例方法
...     self.age = age
...
>>> from types import MethodType
>>> s.set_age = MethodType(set_age, s) # 给实例绑定一个方法
>>> s.set_age(25) # 调用实例方法
>>> s.age # 测试结果
25

但是,给一个实例绑定的方法,对另一个实例是不起作用的:

>>> s2 = Student() # 创建新的实例
>>> s2.set_age(25) # 尝试调用方法
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'set_age'

为了给所有实例都绑定方法,可以给class绑定方法:

>>> def set_score(self, score):
...     self.score = score
...
>>> Student.set_score = set_score

给class绑定方法后,所有实例均可调用:

>>> s.set_score(100)
>>> s.score
100
>>> s2.set_score(99)
>>> s2.score
99

通常情况下,上面的set_score方法可以直接定义在class中,但动态绑定允许我们在程序运行的过程中动态给class加上功能,这在静态语言中很难实现。

使用__slots__

但是,如果我们想要限制实例的属性怎么办?比如,只允许对Student实例添加nameage属性。

为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class实例能添加的属性:

class Student(object):
    __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称

然后,我们试试:

>>> s = Student() # 创建新的实例
>>> s.name = 'Michael' # 绑定属性'name'
>>> s.age = 25 # 绑定属性'age'
>>> s.score = 99 # 绑定属性'score'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'score'

由于'score'没有被放到__slots__中,所以不能绑定score属性,试图绑定score将得到AttributeError的错误。

使用__slots__要注意,__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的:

>>> class GraduateStudent(Student):
...     pass
...
>>> g = GraduateStudent()
>>> g.score = 9999

除非在子类中也定义__slots__,这样,子类实例允许定义的属性就是自身的__slots__加上父类的__slots__



转载。原文:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/00143186739713011a09b63dcbd42cc87f907a778b3ac73000

目录
相关文章
|
7月前
|
C语言 iOS开发 MacOS
Objective-C是一种面向对象的编程语言,它扩展了C语言,添加了面向对象编程的特性
【5月更文挑战第9天】Objective-C是苹果公司的面向对象编程语言,用于iOS和macOS应用开发。它扩展了C语言,包含类定义(接口和实现)、对象创建、消息传递、属性、协议、块和类别等语法特性。例如,类通过`@interface`和`@implementation`定义,对象用`alloc`和`init`创建,方法通过消息传递调用。属性简化变量声明,协议定义可选方法集合,块支持代码块作为参数,类别用于扩展已有类。错误处理常使用NSError对象。要深入了解,建议查阅相关教程和文档。
61 0
|
7月前
|
Rust 安全 开发者
Rust中的元编程概念与应用
本文将深入探讨Rust编程语言中的元编程概念,包括宏、特性、元组和元函数等,并展示它们在Rust中的实际应用。元编程允许开发者在编译时操纵代码,实现代码生成、条件编译、类型检查等高级功能。通过本文的讲解,读者将能够更好地理解元编程在Rust中的作用,并学会如何在项目中应用元编程技术。
|
7月前
|
存储 设计模式 人工智能
Rust 笔记:有限状态机原理/状态模式 及其 在Rust 编程中的应用
Rust 笔记:有限状态机原理/状态模式 及其 在Rust 编程中的应用
392 0
|
7月前
|
Java C# 数据安全/隐私保护
学过了这么多面向对象的编程语言,你知道他们的对象是谁吗?
学过了这么多面向对象的编程语言,你知道他们的对象是谁吗?
73 0
|
SQL Rust 前端开发
Rust学习笔记之面向对象编程
Rust学习笔记之面向对象编程
|
Java
面试--什么是面向对象?面向对象三大特性?
面试--什么是面向对象?面向对象三大特性?
70 0
|
设计模式 Rust Dart
Rust 笔记、设计模式发布订阅模式及其 在 Rust 语言中的使用
本文介绍发布订阅模式的相关思想,以及 Rust 第三方模块 EventEmitter 的使用。
293 0
|
Rust 编译器
Rust面向对象与Trait
Rust面向对象与Trait
|
存储 Rust JavaScript
初识Rust中的面向对象
初识Rust中的面向对象
|
存储 Rust Java
【Rust 课外知识】Rust中的三种多态性(上)——Enum和Trait
【Rust 课外知识】Rust中的三种多态性(上)——Enum和Trait