相关疑难解决方法(0)

为什么在__new __()后总是调用__init __()?

我只是想简化我的一个类,并引入了一些与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 design-patterns class-design

525
推荐指数
14
解决办法
26万
查看次数

什么是班级工厂?

我经常看到这个词,我可能已经在代码和库中使用了它,但我从来没有真正得到它.在我看到的大多数写作中,他们只是希望你能弄明白.

什么是班级工厂?有人可以解释这个概念吗?

factory class

32
推荐指数
3
解决办法
3万
查看次数

在Python 3.6中将ABCMeta与__init_subclass__组合时的TypeError

我正在尝试将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)

python python-3.6

10
推荐指数
1
解决办法
1688
查看次数

当基类返回可导入模块中的子类实例时,避免循环导入

概括

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)

python inheritance circular-dependency

8
推荐指数
1
解决办法
1567
查看次数

哪种方式最适合Python工厂注册?

这是一个关于这些方法中的哪一个被认为是最Pythonic 的问题。我不是在寻找个人意见,而是在寻找什么是惯用的。我的背景不是 Python,所以这对我有帮助。

我正在开发一个可扩展的 Python 3 项目。这个想法类似于工厂模式,只是它基于函数。

本质上,用户将能够创建一个自定义函数(跨包和项目),我的工具可以找到并动态调用该函数。它还可以使用柯里化来向下传递参数(但此处不包含该代码)

我的目标是遵循良好的 Pythonic 实践。我在两种策略之间左右为难。而且,由于 Python 不是我的专长,我想知道以下做法的优缺点:

  1. 使用装饰器

    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)

    这看起来很合理,但对于那些不熟悉装饰器的人来说确实有点神奇。

  2. 强制对抽象类进行子类化并使用 __subclasses__()

    如果使用子类,则无需注册。但是,我觉得这会在可能不需要完整类时强制定义类。此外,.__subclasses__()引擎盖下的使用对消费者来说也很神奇。但是,即使是 Java 也可以用于搜索带有注释的类。

  3. 显式注册

    忘记以上所有内容并强制显式注册。没有装饰器。没有子类。就像这样:

    def build_foo():
      # ...
    
    factory.register('foo', build_foo)
    
    Run Code Online (Sandbox Code Playgroud)

python idioms python-3.x python-decorators

5
推荐指数
1
解决办法
851
查看次数