我只是想简化我的一个类,并引入了一些与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)
为什么?
我经常看到这个词,我可能已经在代码和库中使用了它,但我从来没有真正得到它.在我看到的大多数写作中,他们只是希望你能弄明白.
什么是班级工厂?有人可以解释这个概念吗?
我正在尝试将python 3.6的新__init_subclass__
功能(PEP 487)与abc
模块一起使用.它似乎没有工作.以下代码:
from abc import ABCMeta
class Initifier:
def __init_subclass__(cls, x=None, **kwargs):
super().__init_subclass__(**kwargs)
print('got x', x)
class Abstracted(metaclass=ABCMeta):
pass
class Thingy(Abstracted, Initifier, x=1):
pass
thingy = Thingy()
Run Code Online (Sandbox Code Playgroud)
运行时产生以下结果:
Traceback (most recent call last):
File "<filename>", line 10, in <module>
class Thingy(Abstracted, Initifier, x=1):
TypeError: __new__() got an unexpected keyword argument 'x'
Run Code Online (Sandbox Code Playgroud)
如果Abstracted不使用ABCMeta
元类,一切正常.
这个错误是相当有弹性的,例如,下面的代码仍然失败并出现类似的类型错误(可能是因为元类' __new__
在类实例化时运行,而父类' __new__
在对象实例化之前不会运行).
from abc import ABCMeta
class Initifier:
def __new__(cls, name, bases, dct, x=None, **kwargs):
return …
Run Code Online (Sandbox Code Playgroud) TLDR:当基类在可导入模块中返回子类实例时,如何避免循环导入错误?
我从其他位置/问题收集了一些解决方案(参见下面的 AD),但恕我直言,没有一个是令人满意的。
# onefile.py
from abc import ABC, abstractmethod
class Animal(ABC):
def __new__(cls, weight: float):
if cls is Animal:
# Try to return subclass instance instead.
for subcls in [Dog, Cat]:
try:
return subcls(weight)
except ValueError:
pass
raise NotImplementedError("No appropriate subclass found.")
return super().__new__(cls)
@property
@abstractmethod
def weight(self) -> float:
"""weight of the animal in kg."""
...
class Dog(Animal):
def __init__(self, weight: float = 5):
if not (1 < weight < …
Run Code Online (Sandbox Code Playgroud) 这是一个关于这些方法中的哪一个被认为是最Pythonic 的问题。我不是在寻找个人意见,而是在寻找什么是惯用的。我的背景不是 Python,所以这对我有帮助。
我正在开发一个可扩展的 Python 3 项目。这个想法类似于工厂模式,只是它基于函数。
本质上,用户将能够创建一个自定义函数(跨包和项目),我的工具可以找到并动态调用该函数。它还可以使用柯里化来向下传递参数(但此处不包含该代码)
我的目标是遵循良好的 Pythonic 实践。我在两种策略之间左右为难。而且,由于 Python 不是我的专长,我想知道以下做法的优缺点:
使用装饰器
registered = {}
def factoried(name):
def __inner_factory_function(fn):
registered[name] = fn
return fn
return __inner_factory_function
def get_function(name):
return registered[name]
Run Code Online (Sandbox Code Playgroud)
然后,下面的函数就自动注册了...
@factoried('foo')
def build_foo():
print('hi')
Run Code Online (Sandbox Code Playgroud)
这看起来很合理,但对于那些不熟悉装饰器的人来说确实有点神奇。
强制对抽象类进行子类化并使用 __subclasses__()
如果使用子类,则无需注册。但是,我觉得这会在可能不需要完整类时强制定义类。此外,.__subclasses__()
引擎盖下的使用对消费者来说也很神奇。但是,即使是 Java 也可以用于搜索带有注释的类。
显式注册
忘记以上所有内容并强制显式注册。没有装饰器。没有子类。就像这样:
def build_foo():
# ...
factory.register('foo', build_foo)
Run Code Online (Sandbox Code Playgroud)python ×4
class ×1
class-design ×1
factory ×1
idioms ×1
inheritance ×1
python-3.6 ×1
python-3.x ×1