社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

在Python中自定义类的创建方式

Python程序员 • 9 年前 • 876 次点击  

Python部落(python.freelycode.com)组织翻译,禁止转载,欢迎转发。


当人们在想要创建一个定制类的时候,他们可能通常想到的是元类和类修饰器。在通常的会话中元类一般作为创建类的开始而类修饰符作为结束。但是您可能不知道的是在类创建中还有另外的两个步骤需要调整:__prepare__()__init_subclass__()(分别在Python3.0和3.6中添加)。


这个__prepare__()钩子用于在构造过程中指定用于类命名空间的对象(对象被复制到一个字典中最后存储到__dict__)。该方法在元类指定,并且在__call__之前调用。历史上__prepare__()方法被用来返回OrderedDict,以便类中事物的定义顺序可以在以后知道。但是由于返回的对象被用作类的命名空间,您还可以用它来注入要在类定义中使用的对象。


从David Beazley得到了一个点子,你可以滥用__prepare__()以致你可以定义一个ABC使得abstractmethod在类定义中隐含了。

使用这个元类你可以得到abstractmethod而不用通过abc来得到它。

这种做法是因为创建类的方式本质上是通过使用类的body并将其传递给exec(),同时使用__prepare__()的结果作为区域变量。


另一种调整类创建的方式是__init_subclass__()。当定义类被子类化时,该方法被调用。它传递了提供给类定义行的子类和任何关键字参数。


为了展示一种使用这种方式的方法,我意识到你可以滥用变量类型的注释来形成一个“可怕”版本的Hynek Schlawack的attrs项目。基本上下面的类自动定义一个__init__()和(可选)__repr__()为一个基于变量类型注释的类。

这样就可以创建您可能使用的简单的Python对象types.SimpleNamespace(另外:不要滥用collections.namedtuple来生成一个简单项目;这个类意味着帮助搬运API们来返回一个元组到一个更面向对象的API,所以开始使用namedtuple意味着你最终泄露一个你可能并不想以它开始的元组API)。

您也可以使用类定义的关键字参数来跳过__repr__()定义。

和所有调整类定义的东西一样,你一定要非常小心,不要滥用这些东西。调整怎样进行类创建可能很难调试,只有当您在有真正合法的用例的时候才能使用。但是,如果您遇到使用该代码的代码,或者您真的有需要但没有其他合理选项的时候,那么这个东西值得您了解。


Brett Cannon

Vancouver,BC,Canada


英文原文:https://snarky.ca/customizing-class-creation-in-python/
译者:liuyuexiao



今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/Gc2J9opALz
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/2726