我只是想简化我的一个类,并引入了一些与flyweight设计模式相同的功能.
但是,我有点困惑,为什么__init__总是被称为__new__.我没想到这个.任何人都可以告诉我为什么会这样,以及我如何能够实现这个功能呢?(除了将实施放入__new__感觉相当hacky之外.)
这是一个例子:
class A(object):
_dict = dict()
def __new__(cls):
if 'key' in A._dict:
print "EXISTS"
return A._dict['key']
else:
print "NEW"
return super(A, cls).__new__(cls)
def __init__(self):
print "INIT"
A._dict['key'] = self
print ""
a1 = A()
a2 = A()
a3 = A()
Run Code Online (Sandbox Code Playgroud)
输出:
NEW
INIT
EXISTS
INIT
EXISTS
INIT
Run Code Online (Sandbox Code Playgroud)
为什么?
有没有人曾经使用过C++的"贴牌新品"?如果是这样,那该怎么办?在我看来,它只对内存映射硬件有用.
虽然我从来没有需要这个,但让我感到震惊的是在Python中创建一个不可变对象可能会有点棘手.你不能只是覆盖__setattr__,因为那时你甚至不能设置属性__init__.对元组进行子类化是一种有效的技巧:
class Immutable(tuple):
def __new__(cls, a, b):
return tuple.__new__(cls, (a, b))
@property
def a(self):
return self[0]
@property
def b(self):
return self[1]
def __str__(self):
return "<Immutable {0}, {1}>".format(self.a, self.b)
def __setattr__(self, *ignored):
raise NotImplementedError
def __delattr__(self, *ignored):
raise NotImplementedError
Run Code Online (Sandbox Code Playgroud)
但是你可以通过和访问a和b变量,这很烦人.self[0]self[1]
这在纯Python中是否可行?如果没有,我将如何使用C扩展?
(只能在Python 3中使用的答案是可以接受的).
更新:
因此,子类的元组是做纯Python,效果很好,除了通过访问数据的另一种可能性的方式[0],[1]等等.所以,要完成这个问题,所有这一切都缺少的是HOWTO在C,做"正确的",这我怀疑是非常简单,只是没有实现任何geititem或setattribute等等.但我不是自己做,我为此提供赏金,因为我很懒.:)
让我从这开始不重复
为什么__init__如果没有args调用__new__就不会被调用.我试图精心构建了一些示例代码__new__和__init__有没有解释,我可以找到.
基本参数:
__init__方法,反过来调用一个_parse方法_parse子类中的方法super以避免Python日志记录中的问题
:为什么__init__被调用两次?无论如何,__init__应该在之后调用__new__以及为什么下面的一些样本不起作用的每个解释我似乎能够指出其他有用的情况并排除解释.
class NotMine(object):
def __init__(self, *args, **kwargs):
print "NotMine __init__"
self._parse()
def _parse(self):
print "NotMine _parse"
class ABC(NotMine):
def __new__(cls,name,*args, **kwargs):
print "-"*80
print "Entered through the front door ABC.__new__(%s,%s,*%s,**%s)"%(cls,name,args,kwargs)
if name == 'AA':
obj = super(NotMine,ABC).__new__(AA,*args,**kwargs)
print "Exiting door number 1 with an instance of: %s"%type(obj)
return obj
elif …Run Code Online (Sandbox Code Playgroud) 在基本上处理自定义枚举类型实现时,我遇到了这样一种情况:我必须从两者中派生出单独但几乎相同的子类int,long因为它们是Python中的不同类.这似乎有点讽刺意味,因为两者的实例通常可以互换使用,因为大多数情况下它们只是在需要时自动创建.
我的工作很好,但本着DRY(不要重复自己)的精神,我不禁想知道是否有更好的,或者至少更简洁的方式来实现这一点.目标是让子类实例可以在任何地方使用 - 或尽可能接近 - 它们的基类实例可以使用.理想情况下,这应该自动发生,类似于内置int()实际返回的方式,long只要它检测到一个是必需的.
这是我目前的实施:
class NamedInt(int):
"""Subclass of type int with a name attribute"""
__slots__ = "_name" # also prevents additional attributes from being added
def __setattr__(self, name, value):
if hasattr(self, name):
raise AttributeError(
"'NamedInt' object attribute %r is read-only" % name)
else:
raise AttributeError(
"Cannot add attribute %r to 'NamedInt' object" % name)
def __new__(cls, name, value):
self = super(NamedInt, NamedInt).__new__(cls, value)
# avoid call to …Run Code Online (Sandbox Code Playgroud) 我正在阅读关于元类的这篇有趣的帖子什么是Python中的元类?.接受的答案显示了如何使用具有以下签名的类型创建类.
type(类的名称,父类的元组(用于继承,可以为空),包含属性名称和值的字典)
我尝试使用上面的签名创建"类型"类,我很惊讶我被允许创建一个首先!您的意见表示赞赏!
type = type('type',(),{});
其次,在使用上述语法创建类型类之后,我无法做到
myclass = type('myclass',(),{});
Run Code Online (Sandbox Code Playgroud)
和
type = type('type',(),{});
我说错了
Traceback(最近一次调用last):TypeError中的文件"",第1行:object.new()不带参数
但是,当我尝试以下内容时,我可以成功.
class myclass(object):
pass
Run Code Online (Sandbox Code Playgroud)
我很困惑,根据我的理解,上面的代码片段应该调用类型来尝试创建类'myclass'.发生什么了!?我错过了一些细节吗?
python ×6
c++ ×1
class ×1
class-design ×1
constructor ×1
genshi ×1
immutability ×1
metaclass ×1
new-operator ×1
object ×1
python-3.x ×1
subclassing ×1