对于递归函数,我们可以:
1 2 3 4 5 6 | def f(i): if i<0: return print i f(i-1) f(10) |
然而,有办法做下面的事情吗?
1 2 3 4 | class A: # do something some_func(A) # ... |
在Python中,您不能在类体中引用类,但在Ruby之类的语言中,您可以这样做。
相反,在Python中,您可以使用类装饰器,但是一旦类初始化,就会调用它。另一种方法是使用元类,但这取决于您想要实现的目标。
您无法使用所描述的特定语法,这是由于它们被计算的时间不同造成的。给出的示例函数能够工作的原因是,在函数体中调用f(i-1)是因为直到实际调用函数时才执行f的名称解析。此时f存在于执行范围内,因为函数已经被求值了。在类示例的情况下,在仍然计算类定义的过程中查找对类名的引用。因此,它还不存在于本地范围中。
或者,可以使用这样的元类来完成所需的行为:
1 2 3 4 5 6 7 8 9 | class MetaA(type): def __init__(cls): some_func(cls) class A(object): __metaclass__=MetaA # do something # ... |
使用这种方法,您可以在计算类时对类对象执行任意操作。
如果你想引用相同的对象,只需使用"self":
1 2 3 | class A: def some_func(self): another_func(self) |
如果你想创建一个相同类的新对象,就这样做:
1 2 3 | class A: def some_func(self): foo = A() |
如果您想访问元类类对象(很可能不是您想要的),同样,只需执行以下操作:
1 2 3 | class A: def some_func(self): another_func(A) # note that it reads A, not A() |
如果你只是想做一件不寻常的事,那就去做
1 2 3 | class A(object): ... some_func(A) |
如果您想做更复杂的事情,可以使用元类。元类负责在类对象完全创建之前操作它。模板应该是:
1 2 3 4 5 6 7 8 9 | class AType(type): def __new__(meta, name, bases, dct): cls = super(AType, meta).__new__(meta, name, bases, dct) some_func(cls) return cls class A(object): __metaclass__ = AType ... |
有关元类的更多信息,请参见http://docs.python.org/reference/datamodel.html#定制类创建。
不。它在函数中工作,因为函数内容是在调用时执行的。但是类内容是在定义时间执行的,此时类还不存在。
这通常不是一个问题,因为你可以在定义了类之后再入侵更多的成员,所以你可以把一个类定义分成多个部分:
1 2 3 4 5 6 7 8 9 10 | class A(object): spam= 1 some_func(A) A.eggs= 2 def _A_scramble(self): self.spam=self.eggs= 0 A.scramble= _A_scramble |
然而,在类的定义中间调用函数是非常不寻常的。不清楚您想要做什么,但是很可能您最好使用decorator(或者相对较新的类decorator)。
在类范围内没有办法做到这一点,除非首先将a定义为其他东西(然后some_func(a)将执行与预期完全不同的操作)
除非您正在进行某种堆栈检查以向类添加位,否则您为什么要这样做似乎有些奇怪。为什么不直接:
1 2 3 4 5 | class A: # do something pass some_func(A) |
也就是说,在创建完成后,在A上运行some_func。另外,如果想以某种方式修改类a,可以使用类修饰器(在2.6中添加了它的语法)或元类。你能阐明你的用例吗?
如果目标是用类作为参数调用函数
1 2 3 4 5 6 7 8 | def some_func(cls): # Do something print(f"The answer is {cls.x}") return cls # Don't forget to return the class @some_func class A: x = 1 |
如果你想传递额外的参数给
1 2 3 4 5 6 7 8 9 | def some_other_func(prefix, suffix): def inner(cls): print(f"{prefix} {cls.__name__} {suffix}") return cls return inner @some_other_func("Hello"," and goodbye!") class B: x = 2 |
类修饰符可以被组合,这导致调用它们的顺序与声明它们的顺序相反:
1 2 3 4 | @some_func @some_other_func("Hello","and goodbye!") class C: x = 42 |
其结果是:
1 2 | # Hello C and goodbye! # The answer is 42 |
如果类实际上在作用域中,那么可以在类的主体中引用类的名称(就像在方法定义中一样)。如果是在顶层定义的。(在其他情况下可能不会,因为Python的作用域的怪癖!)
要说明作用域的问题,请尝试实例化Foo:
1 2 3 4 5 6 7 | class Foo(object): class Bar(object): def __init__(self): self.baz = Bar.baz baz = 15 def __init__(self): self.bar = Foo.Bar() |
(它会抱怨没有定义全局名称"Bar"。)
另外,有件事告诉我,您可能想研究类方法:关于classmethod函数的docs(用作装饰器),这是一个相关的SO问题。编辑:好的,所以这个建议可能根本不合适……我在阅读你的问题时首先想到的是替代构造函数等。如果有一些更简单的东西适合你的需要,那就避开奇怪的东西。:-)
你想达到什么目标?可以使用元类访问类来调整其定义,但不建议这样做。
你的代码样本可以简单地写成:
1 2 3 | class A(object): pass some_func(A) |
类中的大多数代码都在方法定义中,在这种情况下,您可以简单地使用名称