python元编程之使用动态属性实现定制类--特殊方法__setattr__,__getattribute__篇

问题:实现一个类,要求行为如同namedtuple:只存在给定名称的属性,不允许动态添加实例属性。

主要知识点在于: __setattr__,__getattr__,getattribute__,__delattr__特殊方法的实现使用。

代码如下:

 1 """
 2 运行环境
 3 python 3.7+
 4 """
 5 from collections OrderedDict, namedtuple
 6 #以下为要包装的对象:1个命名元组,用于存储计数,并对外传递信息
 7 Counter = namedtuple("Counter", "total put OK failed recorded keys count",
 8                      defaults=(0, 0, 0, 0, 0, 0, 0))
 9 class CounterClass:
10         """
11         内部计数的自定义类,
12         维护一个namedtuple[Counter]
13         """
14
15         def __init__(self):
16             # _dict用于实际保存并计数
17             self._dict = OrderedDict(Counter._fields_defaults)
18
19         def __setattr__(self, name, value):
20             """所有的赋值操作都会调用"""
21             #阻止对_dict的直接赋值
22             if (name == ‘_dict‘ and hasattr(self,‘_dict‘) and isinstance(getattr(self, ‘_dict‘), OrderedDict)):
23                 raise ValueError(f‘ Forbidden to modify attribute:[{name}]‘)
24             if name==‘_dict‘:  # 本实现将阻止除了更新计数之外的其它设值及增加属性,模拟了namedtuple抛出异常
25                 super().__setattr__(name,value)
26             elif name in self._dict:
27                 self._dict[name] = value
28             else:
29                 raise ValueError(f‘ Got unexpected field names:[{name}]‘)
30
31         def __getattribute__(self, name):
32             """
33             __getattribute__在任何属性查找操作中都会调用(包含特殊属性),所以注意以下要super调用
34             否则会陷入无限递归调用.
35             __getattr__方法则是在本身及其类上查找不到才会调用
36             """
37             # 本实现未考虑特殊属性.实际应用时应注意
38             if name in super().__getattribute__(‘_dict‘):
39                 return super().__getattribute__(‘_dict‘)[name]
40             else:
41                 return super().__getattribute__(name)
42
43         def __delattr__(self, name):
44             """拦截了所有删除操作"""
45             raise ValueError(f‘ Forbidden to delete attribute:[{name}]‘)
46
47         def update(self, n: Counter = None, **kargs):
48             """
49             使用数值累加计数器
50             当Counter与键参数同时提供时,键值为准
51             """

补充说明,以上部分逻辑并未完整考虑和优化,只是对特殊方法的实现和利用做演示。如果只是模仿命名数组,最简单的就是从命名数组继承即可。

但是根据业务需求,可能需要实现自己的定制类,以上的特殊方法使用就是python元编程中实现动态属性的重要基础。

下一篇将演示用描述符、__slots__、及__new__实现同样功能的类。

原文地址:https://www.cnblogs.com/zward/p/10041162.html

时间: 2024-11-06 07:15:29

python元编程之使用动态属性实现定制类--特殊方法__setattr__,__getattribute__篇的相关文章

Python元编程

简单定义"元编程是一种编写计算机程序的技术,这些程序可以将自己看做数据,因此你可以在运行时对它进行内审.生成和/或修改",本博参考<<Python高级编程>>将对元编程内容进行详细描述,若有不正确之处希望大家指出. 1. 概述 Python元编程有两种方法,一是采用类似"装饰器"的工具对基本元素(例如函数.类.类型)内审和对其进行实时创建和修改,二是运用类型"元类"的方式对类实例的创建过程进行修改,甚至于允许重新设计Pyt

换个角度理解python元编程

元编程这个概念本身不新,只是没有发现原来很早就在用这个东西,所以python等下再聊,先理一理怎么理解编程这个事情.我仔细思考,其实是在做一件设计想法,纪录想法,实现想法的过程.怎么样设计想法?应该需要一些图形,文字通过一定格式纪录下来,反复修改,最好是有一个规范或者工具让其他人也能明白和理解,方便交流.这个问题在编程这里也就是进入到编程语言的选择上面来,也可以自己制定一个规范,不管你用lex+yacc语法制导还是设计LLVM的AST,反正结果是要一种编程语言来设计你的想法.选定了设计想法的规范

python开发学习-day07(面向对象之多态、类的方法、反射、新式类and旧式类、socket编程)

s12-20160227-day07 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* BLOCKS =============================================================================*/ p, blockquote, ul, ol, dl, table, pre { margin

Python 定制类 特殊方法

1.特殊方法 定义在class中 不需要直接调用,python的某些函数或操作符会自动的调用对应的特殊方法. 如定义了person类,使用print p 语句打印person类的实例时,就调用了特殊方法__str__() 此时就需要在person类中实现这个方法. 使用特殊方法时注意: 只需要编写用到的特殊方法 有关联性的特殊方法都必须实现(如__getattr__,__setattr__,delattr__) 2.python中 __str__和__repr__ __str__()用于显示给用

13 面向对象编程 - 《Python 核心编程》

?? 引言 ?? 面向对象编程 ?? 类 ?? 实例 ?? 绑定与方法调用 ?? 子类,派生和继承 ?? 内建函数 ?? 定制类 ?? 私有性 ?? 授权与包装 ?? 新式类的高级特性 ?? 相关模块 13.1 介绍 在Python 中,面向对象编程主要有两个主题,就是类和类实例 类与实例 如何创建一个类: class MyNewObjectType(bases): 'define MyNewObjectType class' class_suite #类体 关键字是class,紧接着是一个类名

python元类深入理解

1.python 中的类 在python中,类也是一个对象,只不过这个对象拥有生成实例的能力,我们一般使用class XXX来定义一个类,在python解释器执行到这个地方的时候会自动创建出这个对象,python也为我们提供了手动创建类的方法,type().type()这个方法对我们来说并不陌生,我们所熟知的用法是:class = type(instance),当传入一个参数时,type()返回这个参数的类.而今天我们要用到的是type的另一个功能.type("classname",(

Python 炫技操作:合并字典的七种方法

首发于微信公众号:<Python编程时光> Python 语言里有许多(而且是越来越多)的高级特性,是 Python 发烧友们非常喜欢的.在这些人的眼里,能够写出那些一般开发者看不懂的高级特性,就是高手,就是大神. 但你要知道,在团队合作里,炫技是大忌. 为什么这么说呢?我说下自己的看法: 越简洁的代码,越清晰的逻辑,就越不容易出错: 在团队合作中,你的代码不只有你在维护,降低别人的阅读/理解代码逻辑的成本是一个良好的品德 简单的代码,只会用到最基本的语法糖,复杂的高级特性,会有更多的依赖(如

90%人不知道的Python炫技操作:合并字典的七种方法

Python 语言里有许多(而且是越来越多)的高级特性,是 Python 发烧友们非常喜欢的.在这些人的眼里,能够写出那些一般开发者看不懂的高级特性,就是高手,就是大神. 但你要知道,在团队合作里,炫技是大忌. 为什么这么说呢?我说下自己的看法: 越简洁的代码,越清晰的逻辑,就越不容易出错: 在团队合作中,你的代码不只有你在维护,降低别人的阅读/理解代码逻辑的成本是一个良好的品德 简单的代码,只会用到最基本的语法糖,复杂的高级特性,会有更多的依赖(如语言的版本) 该篇是「炫技系列」的第二篇内容,

python高级编程之元类(第3部分结束)

# -*- coding: utf-8 -*- # python:2.x __author__ = 'Administrator' #元编程 #new-style类带来了一种能力,通过2个特殊方法(__new__和__metaclass__)在运行时修改类和对象的定义 #__new__方法 #它是一上元构建程序,每次一个对象被factor类实例化时就调用它 #例如: class A(object): def __new__(cls,): print '__new__' return object