相关疑难解决方法(0)

@property装饰器如何工作?

我想了解内置函数的property工作原理.令我困惑的是,property它也可以用作装饰器,但它只在用作内置函数时才需要参数,而不是用作装饰器时.

这个例子来自文档:

class C(object):
    def __init__(self):
        self._x = None

    def getx(self):
        return self._x
    def setx(self, value):
        self._x = value
    def delx(self):
        del self._x
    x = property(getx, setx, delx, "I'm the 'x' property.")
Run Code Online (Sandbox Code Playgroud)

property的论点是getx,setx,delx和文档字符串.

在下面的代码中property用作装饰器.它的对象是x函数,但在上面的代码中,参数中没有对象函数的位置.

class C(object):
    def __init__(self):
        self._x = None

    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x

    @x.setter
    def x(self, value):
        self._x = value

    @x.deleter
    def x(self):
        del self._x
Run Code Online (Sandbox Code Playgroud)

而且,如何在 …

python properties decorator python-internals python-decorators

889
推荐指数
12
解决办法
46万
查看次数

在Python中创建单例

这个问题不是讨论单身人士设计模式是否可取,反模式,还是任何宗教战争,而是讨论如何以最蟒蛇的方式在Python中最好地实现这种模式.在这种情况下,我将"最pythonic"定义为表示它遵循"最小惊讶原则".

我有多个类可以成为单例(我的用例是记录器,但这并不重要).当我可以简单地继承或装饰时,我不希望在添加gumph的几个类中混乱.

最好的方法:


方法1:装饰者

def singleton(class_):
    instances = {}
    def getinstance(*args, **kwargs):
        if class_ not in instances:
            instances[class_] = class_(*args, **kwargs)
        return instances[class_]
    return getinstance

@singleton
class MyClass(BaseClass):
    pass
Run Code Online (Sandbox Code Playgroud)

优点

  • 装饰器的添加方式通常比多重继承更直观.

缺点

  • 虽然使用MyClass()创建的对象将是真正的单例对象,但MyClass本身是一个函数,而不是一个类,因此您无法从中调用类方法.也是为了m = MyClass(); n = MyClass(); o = type(n)();那时m == n && m != o && n != o

方法2:基类

class Singleton(object):
    _instance = None
    def __new__(class_, *args, **kwargs):
        if not isinstance(class_._instance, class_):
            class_._instance = object.__new__(class_, *args, **kwargs)
        return class_._instance

class MyClass(Singleton, …
Run Code Online (Sandbox Code Playgroud)

python singleton metaclass decorator base-class

829
推荐指数
14
解决办法
29万
查看次数

使用元类的__call__方法而不是__new__?

在讨论元类时,文档说明:

您当然也可以覆盖其他类方法(或添加新方法); 例如__call__(),在调用类时,在元类中定义自定义方法允许自定义行为,例如,并不总是创建新实例.

我的问题是:假设我想在调用类时有自定义行为,例如缓存而不是创建新对象.我可以通过覆盖__new__类的方法来做到这一点.我什么时候想要定义一个元类__call__?这种方法给出了什么,这是不可能实现的__new__

python oop metaclass

35
推荐指数
4
解决办法
2万
查看次数

Asyncio与Gevent

背景

我曾经在一个Python2系统上工作,该系统具有许多同步编写的自定义I / O代码,并使用线程进行了扩展。在某个时候,我们无法进一步扩展它,并意识到我们必须切换到异步编程。

  • Twisted是最受欢迎的选择,但我们想避免其回调地狱。
  • 它确实具有@inlineCallbacks装饰器,该装饰器与其他一些库一样,使用生成器魔术有效地实现了协程。那是可以忍受的,但感觉有点片状。
  • 然后我们找到了gevent。您要做的只是:
from gevent import monkey
monkey.patch_all()
Run Code Online (Sandbox Code Playgroud)

就像那样,您的所有标准I / O(套接字,数据库事务以及用纯Python编写的所有内容)实际上都是异步的,使用greenlet产生并在后台切换。

这不是完美的:

  • 那时,它在Windows上运行不佳(并且今天仍然有一些限制)。幸运的是,我们在Linux上运行。
  • 它不能猴子补丁C扩展,因此,例如,我们不能使用MySQLdb。幸运的是,有许多纯Python替代品,例如PyMySQL。

如今,Python 3更加流行,并且有了它-asyncio。就个人而言,我认为这很棒,但是最近有人问我,它比我们使用gevent做的更好吗?无法给出足够好的答案。

这听起来可能是主观的,但是我实际上是在寻找一个实际的用例,其中一个将大大优于另一个,或者允许另一个不这样做。到目前为止,这是我收集的注意事项:

  1. 就像我说的那样,gevent在Windows上非常受限制。再说一次,我所知道的大多数生产代码都在Linux上运行。

    如果需要在Windows上运行,请使用asyncio

  2. Gevent无法猴子C扩展。但是,asyncio无法猴子修补任何东西

    想象一下,出现了一种新的数据库技术,并且您想使用它,但是它没有一个纯Python库,因此您无法将其与Gevent集成。问题是,当没有可以与asyncio集成的io *库时,您就像被困一样!当然,有工作线程和执行程序,但这不是重点,无论如何在两种情况下都一样好。

  3. 有人说这是个人喜好,但我认为可以说同步编程从本质上讲要比异步编程更容易(请考虑一下:您是否遇到过可以使用套接字的新手程序员,但是很难理解如何正确选择/投票,或考虑期货/承诺?您遇到过相反的情况吗?)。

    无论如何,我们不要去那里。我想解决这一点,因为它经常出现(这是关于reddit的讨论),但是我真正要关注的是您有实际理由使用其中一种的情况。

  4. Asyncio是标准库的一部分。这是巨大的:这意味着它得到了很好的维护,良好的记录,并且每个人都知道它并默认使用它。

    但是,考虑到您需要使用Gevent的知识很少(并且它也得到很好的维护和记录),它似乎并不重要。因此,即使对于涉及期货的最复杂的方案,StackOverflow上也有多个答案,但根本不使用期货的可能性似乎也是可行的。

那么:asyncio盛行的一些具体用例是什么?当然,Guido和Python社区有充分的理由对此投入大量精力,甚至在语言中引入了新的关键字-我似乎找不到它们。

python gevent python-asyncio

18
推荐指数
1
解决办法
4378
查看次数

`classmethod` 和元类方法有什么区别?

在 Python 中,我可以使用@classmethod装饰器创建一个类方法:

>>> class C:
...     @classmethod
...     def f(cls):
...             print(f'f called with cls={cls}')
...
>>> C.f()
f called with cls=<class '__main__.C'>
Run Code Online (Sandbox Code Playgroud)

或者,我可以在元类上使用普通(实例)方法:

>>> class M(type):
...     def f(cls):
...             print(f'f called with cls={cls}')
...
>>> class C(metaclass=M):
...     pass
...
>>> C.f()
f called with cls=<class '__main__.C'>
Run Code Online (Sandbox Code Playgroud)

如 的输出所示C.f(),这两种方法提供了相似的功能。

@classmethod在元类上使用和使用普通方法有什么区别?

python methods metaclass class-method

14
推荐指数
1
解决办法
633
查看次数