假设我正在宣布一个班级 C 其中一些声明非常相似。我想使用一个函数 f 减少这些声明的代码重复。可以只声明和使用 f 照常:

>>> class C(object):
...     def f(num):
...             return '<' + str(num) + '>'
...     v = f(9)
...     w = f(42)
... 
>>> C.v
'<9>'
>>> C.w
'<42>'
>>> C.f(4)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unbound method f() must be called with C instance as first argument (got int instance instead)

哎呀!我不经意间就暴露了 f 对外,但并不需要 self 争论(并且由于明显的原因不能)。一种可能性是 del 我使用后的功能:

>>> class C(object):
...     def f(num):
...             return '<' + str(num) + '>'
...     v = f(9)
...     del f
... 
>>> C.v
'<9>'
>>> C.f
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'C' has no attribute 'f'

但是如果我想使用怎么办 f 稍后再说,在声明之后?删除该功能是不行的。我可以将其设为“私有”(即,在其名称前加上前缀) __)并给它 @staticmethod 治疗,但调用 staticmethod 通过异常通道的对象变得非常时髦:

>>> class C(object):
...     @staticmethod
...     def __f(num):
...             return '<' + str(num) + '>'
...     v = __f.__get__(1)(9)   # argument to __get__ is ignored...
... 
>>> C.v
'<9>'

我必须使用上面的疯狂因为 staticmethod 对象是描述符,其本身不可调用。我需要恢复由 staticmethod 在我可以调用它之前对象。

必须有更好的方法来做到这一点。如何在类中干净地声明一个函数,在声明期间使用它,以及稍后在类中使用它?我应该这样做吗?

有帮助吗?

解决方案

很简单,解决方案是f不需要是该类的成员。我假设你的思维过程经历了一个导致心理障碍的Javaish语言过滤器。它有点像这样:

def f(n):
    return '<' + str(num) + '>'

class C(object):

    v = f(9)
    w = f(42)

然后当你想再次使用f时,只需使用它

>>> f(4)
'<4>'

我认为这个故事的寓意是<!>;在Python中,你没有拥有来强迫所有东西进入类<!>“;

其他提示

扩展 Ali A 的回答, 如果你真的想避免模块命名空间中的f(并使用像_f这样的非导出名称,或设置__all__是不够的),那么 你可以通过在闭包中创建类来实现这一点。

def create_C():
    def f(num):
        return '<' + str(num) + '>'

    class C(object):
        v = f(9)
        def method_using_f(self, x):  return f(x*2)
    return C

C=create_C()
del create_C

这样C可以在其定义和方法中访问f,但没有其他方法可以访问f(除非涉及内省 其方法(C.method_using_f.im_func.func_closure))

这对于大多数目的来说可能有点过分了 - 通过使用<!>“<!>来记录f是内部的;前缀命名约定应该 通常就够了。

[编辑] 另一个选项是在您希望使用它的方法中保存对预包装函数对象的引用。例如,通过将其设置为默认参数:

class C(object):
    def f(num):
        return '<' + str(num) + '>'

    v = f(9)
    def method_using_f(self, x, f=f):  return f(x*2)

    del f

(虽然我认为封闭方法可能更好)

这是一种可能性:

class _C:
    # Do most of the function definitions in here
    @classmethod
    def f(cls):
        return 'boo'

class C(_C):
    # Do the subsequent decoration in here
    v = _C.f()

我相信你正在尝试这样做:

class C():
...     class F():
...         def __call__(self,num):
...             return "<"+str(num)+">"
...     f=F()
...     v=f(9)
>>> C.v
'<9>'
>>> C.f(25)
'<25>'
>>> 

也许有更好或更多的pythonic解决方案......

  

<!> quot;在类中声明一个函数,在声明过程中使用它,稍后在类<!>中使用它;

     

对不起。无法完成。

<!>“无法完成<!>”;似乎与Python不相处

一个选项:写一个更好的staticmethod

class staticfunc(object):
    def __init__(self, func):
        self.func = func
    def __call__(self, *args, **kw):
        return self.func(*args, **kw)
    def __repr__(self):
        return 'staticfunc(%r)' % self.func

让我们从头开始吧。

“在类中声明一个函数,在声明期间使用它,然后在类中使用它”

对不起。做不到。“在类中”与“在声明期间使用”相矛盾。

  • 在类中意味着作为声明的一部分创建。
  • 在声明期间使用意味着它存在于类之外。通常作为元类。然而,还有其他方法。

目前尚不清楚 C.w 和 C.v 应该是什么。它们只是字符串吗?如果是这样,则外部函数 f 是最好的解决方案。“不要使命名空间混乱”有点似是而非。毕竟,您想再次使用它。

它与 C 位于同一模块中。这就是 Python 有模块的原因。它将函数和类绑定在一起。

import myCmod

myCmod.C.w
myCmod.C.v
myCmod.f(42)

如果 w 和 v 不是简单的字符串,那么有一个非常好的解决方案,可以提供很大的灵活性。

一般来说,对于像这样的类级(“静态”)变量,我们可以使用其他类。完全实现所需的 API 是不可能的,但已经很接近了。

>>> class F(object):
    def __init__( self, num ):
        self.value= num
        self.format= "<%d>" % ( num, )

>>> class C(object):
    w= F(42)
    v= F(9)

>>> C.w
<__main__.F object at 0x00C58C30>
>>> C.w.format
'<42>'
>>> C.v.format
'<9>'

这样做的好处是F是一个合适的、一流的东西,可以扩展。这不是我们试图避免暴露的“隐藏”的事情。这是生活中的事实,因此我们不妨遵循开放/封闭原则并使其开放以进行扩展。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top