【发布时间】:2018-08-30 06:32:41
【问题描述】:
我需要编写几十个类,它们仅通过变量彼此不同,这对于类的稳定工作至关重要。没有这样的变量,类就无法工作,变量的改变可能会破坏它们。我已经编写了一个用于创建相应 metaclss 的代码:
from abc import ABCMeta, abstractmethod, abstractproperty
import re
def get_field_protector(*names):
def check_attributes(cls):
for t in names:
if not hasattr(cls, t):
raise Exception('Abstract field "{0}" have to be defined'.format(t))
def decorate_new_method(inp_method, class_name):
def inner(cls, *args, **kwargs):
if cls.__new__.decorated==class_name:
check_attributes(cls)
return inp_method(cls, *args, **kwargs)
return inner
class result_protector(ABCMeta):
def __setattr__(self, name, value):
if name in names:
raise Exception("Read only class attribute!")
super(self.__class__, self).__setattr__(name, value)
def __delattr__(self, name):
if name in names:
raise Exception("Read only class attribute!")
super(self.__class__, self).__delattr__(name)
def __init__(self, name, bases, attributes):
super(self.__class__, self).__init__(name, bases, attributes)
if not hasattr(self.__new__, 'decorated'):
self.__new__=decorate_new_method(self.__new__, name)
self.__new__.decorated=name
return result_protector
在我开始使用以下类之前它工作正常:
class test(object, metaclass=get_field_protector("essential_field")):
essential_field="some_value"
def __init__(self, val):
self.val=val
当我尝试创建此类时,我收到:
>>> test(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/media/bykov/9016-4EF8/main_architecture.py", line 13, in inner
return inp_method(cls, *args, **kwargs)
TypeError: object() takes no parameters
【问题讨论】:
-
永远不要将
type(self)(或self.__class__,这是一回事)传递给super!您的问题被标记为python-3.x,因此请改用super()。见Shortcut for super(type(self), self)。 -
你真的需要那个防御吗? Python 是一种动态语言,它更多地依赖于约定和适当的文档,而不是语言强制的限制,试图与 Python 的本质作斗争大多是浪费时间。
-
@brunodesthuilliers 这不应该是重复的。它不能解决问题。
-
我不明白你为什么要覆盖/装饰类的
__new__方法。您知道每次创建test类的instance 时都会调用__new__,对吧?为什么每次创建新实例时都需要调用check_attributes?您不能在创建类后调用一次吗? -
@Aran-Fey 也许你是对的。如果重新定义 new 方法,用户必须执行 super().__new__(cls, *args, **kwargs)
标签: python python-3.x metaprogramming