class MyClass(object):
def __init__(self, name, *args, **kwargs):
self.name = name
显然,实例可以与此同名。让我们使用metaclass(使用兼容的python2/3语法)
^{pr2}$
哪些输出:
a.name: hello
b.name: goodbye
Duplicate Name caught
使用metaclass技术,您甚至可以避免使用name作为参数,并且可以为每个实例自动生成名称。在
import itertools
class MyMeta(type):
_counter = itertools.count()
@classmethod
def as_metaclass(meta, *bases):
'''Create a base class with "this metaclass" as metaclass
Meant to be used in the definition of classes for Py2/3 syntax equality
Args:
bases: a list of base classes to apply (object if none given)
'''
class metaclass(meta):
def __new__(cls, name, this_bases, d):
# subclass to ensure super works with our methods
return meta(name, bases, d)
return type.__new__(metaclass, str('tmpcls'), (), {})
def __call__(cls, *args, **kwargs):
obj = type.__call__(cls, *args, **kwargs)
obj.name = '%s_%d' % (cls.__name__, next(cls._counter))
return obj
class MyClass(MyMeta.as_metaclass()):
pass
a = MyClass()
print('a.name:', a.name)
b = MyClass()
print('b.name:', b.name)
c = MyClass()
print('c.name:', c.name)
class Foo():
_names = set()
@property
def name(self):
return self._name
def __init__(self, name):
if name in Foo._names:
raise NameError("Already used name '%s'." % name)
self._name = name
Foo._names.add(name)
您可以使用元类控制实例创建(例如),并确保名称是唯一的。假设
__init__
方法接受一个没有默认值的参数name
显然,实例可以与此同名。让我们使用
^{pr2}$metaclass
(使用兼容的python2/3语法)哪些输出:
使用
metaclass
技术,您甚至可以避免使用name
作为参数,并且可以为每个实例自动生成名称。在输出:
要完成关于防止
a.name = b.name
(或任何其他已在使用的名称)的问题和答案,可以使用基于descriptor
的方法具有预期的输出(在
__init__
或赋值期间不能重用名称)编辑:
由于OP赞成这种方法,因此}的组合方法包括:
metaclass
和{name
类属性作为descriptor
在类创建过程中由metaclass
添加name
在实例到达__init__
之前每个实例初始化一次name
赋值操作的唯一性在}来消除类本身的污染
descriptor
类中存储控制名称唯一性的set
和{预期输出:
对我来说,这比搞乱元类等要简单得多。如果你需要对几个类这样做,元类更有意义。在
使name成为不带write方法的属性会导致赋值失败,从而有效地使
name
为常量。在如果子类
Foo
,则它在所有子类中保持相同的名称集,这可能是也可能不是您想要的。在相关问题 更多 >
编程相关推荐