我想建立与此类取默认值的参数在类中的方法。 总的来说,我做过滤一些数据。 在我的班级我有而正常情况下我通过数据载体的方法。 有时候,我没有载体和我带的模拟数据。 每次我没有通过一个特定的载体,我想在默认情况下采取模拟数据。 我认为这应该是一个简单的构造,其中我的方法定义里面我说a=self.vector
。 但由于某些原因,我有一个错误NameError: name 'self' is not defined
。 简化的结构是:
class baseClass(object): # This class takes an initial data or simulation
def __init__(self):
self.x = 1
self.y = 2
class extendedClass(baseClass): # This class does some filtering
def __init__(self):
baseClass.__init__(self)
self.z = 5
def doSomething(self, a=self.z):
self.z = 3
self.b = a
if __name__ == '__main__':
a = extendedClass()
print a.__dict__
a.doSomething()
print a.__dict__
我预期的输出应该是:
{'y': 2, 'x': 1, 'z': 5}
{'y': 2, 'x': 1, 'z': 3, 'b': 5}
我试图默认分配为def doSomething(self, a=z):
很明显这并不永远工作。 据我了解self.z
是在此范围内可见的,不应该把它作为一个默认值的问题。 不知道为什么我有这样的错误,以及如何做到这一点。 这可能是一个简单的问题,但我揣摩出或找到不缺了一段时间已经解决。 我发现类似的问题,只为其他语言。
你的理解是错误的。 self
本身就是一个参数,该函数的定义,那么有没有办法可以在这一点上是在范围内。 这是只有在函数内部的范围。
答案很简单,就是默认的参数None
,然后检查,该方法中:
def doSomething(self, a=None):
if a is None:
a = self.z
self.z = 3
self.b = a
下面的代码为一个简单的例子模块拆卸。 A码对象为字节码时,它使用的常数和名称,和元数据的本地变量的数量,所需的堆栈大小等的只读容器注意,所有代码对象的被编译为常数。 这些都是在编译时创建的。 但对象class A
和function test
是在执行时(例如,当模块被导入)实例化。
为了使课堂, BUILD_CLASS
取名字'A'
,该基地tuple
(object,)
,以及dict
包含类的命名空间的属性。 这就像通过调用手动实例化一个类型type(name, bases, dict)
。 为了使dict
,从编码对象创建一个功能A
叫。 最后,类对象被存储在经由模块命名空间STORE_NAME
。
在代码对象A
, self.z
装入堆栈作为参数上MAKE_FUNCTION
。 字节码运算LOAD_NAME
将搜索self
当前当地人(即正在定义的类命名空间),该模块全局变量,和内置函数。 如果这显然不能self
未在全局或内建范围定义; 它显然不是在本地范围内定义。
如果没有成功,但是,该功能将与创建(self.z,)
作为其__defaults__
属性,然后存储到本地名称test
。
>>> code = compile('''
... class A(object):
... def test(self, a=self.z): pass
... ''', '<input>', 'exec')
>>> dis.dis(code)
2 0 LOAD_CONST 0 ('A')
3 LOAD_NAME 0 (object)
6 BUILD_TUPLE 1
9 LOAD_CONST 1 (<code object A ...>)
12 MAKE_FUNCTION 0
15 CALL_FUNCTION 0
18 BUILD_CLASS
19 STORE_NAME 1 (A)
22 LOAD_CONST 2 (None)
25 RETURN_VALUE
>>> dis.dis(code.co_consts[1]) # code object A
2 0 LOAD_NAME 0 (__name__)
3 STORE_NAME 1 (__module__)
3 6 LOAD_NAME 2 (self)
9 LOAD_ATTR 3 (z)
12 LOAD_CONST 0 (<code object test ...>)
15 MAKE_FUNCTION 1
18 STORE_NAME 4 (test)
21 LOAD_LOCALS
22 RETURN_VALUE
@uselpa:您的引擎收录的例子(改写2.X):
>>> code = compile('''
... default = 1
... class Cl(object):
... def __init__(self, a=default):
... print a
... Cl()
... default = 2
... Cl()
... ''', '<input>', 'exec')
>>> dis.dis(code)
2 0 LOAD_CONST 0 (1)
3 STORE_NAME 0 (default)
3 6 LOAD_CONST 1 ('Cl')
9 LOAD_NAME 1 (object)
12 BUILD_TUPLE 1
15 LOAD_CONST 2 (<code object Cl ...>)
18 MAKE_FUNCTION 0
21 CALL_FUNCTION 0
24 BUILD_CLASS
25 STORE_NAME 2 (Cl)
6 28 LOAD_NAME 2 (Cl)
31 CALL_FUNCTION 0
34 POP_TOP
7 35 LOAD_CONST 3 (2)
38 STORE_NAME 0 (default)
8 41 LOAD_NAME 2 (Cl)
44 CALL_FUNCTION 0
47 POP_TOP
48 LOAD_CONST 4 (None)
51 RETURN_VALUE
正如你所看到的,类对象Cl
(和函数对象__init__
)只实例化和存储到本地名称'Cl'
一次。 该模块在运行时依次执行,所以随后重新绑定的名称default
将对默认值没有影响__init__
。
你可以使用以前编译代码和一个新的默认值动态实例化一个新功能:
>>> default = 1
>>> class Cl(object):
... def __init__(self, a=default):
... print a
...
>>> from types import FunctionType
>>> default = 2
>>> Cl.__init__ = FunctionType(
... Cl.__init__.__code__, globals(), '__init__', (default,), None)
>>> c = Cl()
2
这重用从已编译的代码对象__init__.__code__
创建功能与新的__defaults__
元组:
>>> Cl.__init__.__defaults__
(2,)
默认参数得到评估一次,在执行的定义。 相反,这样做:
def doSomething(self, a=None):
if a is None:
a = self.z
self.z = 3
self.b = a
又见http://docs.python.org/release/3.3.0/tutorial/controlflow.html#more-on-defining-functions 。
这将插入self.z
如果a
是None
/ False
/ empty_value
:
def doSomething(self, a=None):
self.z = 3
self.b = (a or self.z)