以下是我将称之为“隐式”的方法来定义一个类:
class Super:
pass
class Klass1(Super):
a = 1
i = 4
def get_i(self):
return self.i
以下是尝试“明确”定义类似上面的类:
get_i = lambda self: self.i
dct = dict(a=1, i=4, get_i=get_i)
Klass2 = type('Klass2', (Super,), dct)
但是,Klass1
和Klass2
不相同,如以下测试所示:
import inspect
import types
LambdaType = type(lambda:0)
dollar_param_lines = ['isinstance($, types.LambdaType)',
'isinstance($, LambdaType)',
'$.__name__',
'$.__qualname__',
'type($)',
'inspect.isfunction($)',
'inspect.ismethod($)',
]
for p_line in dollar_param_lines:
for kls_name in ('Klass1', 'Klass2'):
# get_i = getattr(kls, 'get_i')
unparam_line = p_line.replace('$', kls_name + '.get_i')
result = eval(unparam_line)
result = str(result)
print(unparam_line.ljust(45), result)
我正在使用的python发行版的输出是:
isinstance(Klass1.get_i, types.LambdaType) True
isinstance(Klass2.get_i, types.LambdaType) True
isinstance(Klass1.get_i, LambdaType) True
isinstance(Klass2.get_i, LambdaType) True
Klass1.get_i.__name__ get_i
Klass2.get_i.__name__ <lambda>
Klass1.get_i.__qualname__ Klass1.get_i
Klass2.get_i.__qualname__ <lambda>
type(Klass1.get_i) <class 'function'>
type(Klass2.get_i) <class 'function'>
inspect.isfunction(Klass1.get_i) True
inspect.isfunction(Klass2.get_i) True
inspect.ismethod(Klass1.get_i) False
inspect.ismethod(Klass2.get_i) False
特别是,__name__
和__qualname__
不同。我们如何修改我之前给出的“显式”类定义,以便Klass2
基本上是Klass2
的深层副本,反之亦然。
答案 0 :(得分:2)
您在类Klass1
和Klass2
中看不到任何差异,仅在函数Klass1.get_i
和Klass2.get_i
中。所以你问的是错误的问题。
要验证这一点,请尝试以这种方式定义Klass2
:
def get_i(self):
return self.i
dct = dict(a=1, i=4, get_i=get_i)
Klass2 = type('Klass2', (Super,), dct)
或者,或者以这种方式定义Klass
:
class Klass1(Super):
a = 1
i = 4
get_i = lambda self: self.i
你会发现没有任何区别了。
如果您对def
和lambda
之间的区别感兴趣,我们可以删除所有课程内容并进行比较:
def f(): return 0
g = lambda: 0
但现在应该是显而易见的。 def
语句具有要存储的名称; lambda
表达式没有。事实上,你碰巧将lambda存储在一个名为g
的变量中并不重要。您可以轻松地将其分配给两个变量,或者在不指定它的情况下使用它,或者将其分配给临时未命名对象的属性元素。所以它的名字只是<lambda>
。
如果您进一步深入研究,您会发现LambdaType
和FunctionType
属于同一类型,并且这些函数的唯一属性不同是__name__
和{{ 1}}。
答案 1 :(得分:1)
正如您所说,这两个类之间的唯一区别是您的__name__
函数的__qualname__
和get_i
。因此,使这两个类等效就像将这两个属性设置为正确的值一样简单:
get_i = lambda self: self.i
get_i.__name__ = 'get_i'
get_i.__qualname__ = 'Klass2.get_i'
dct = dict(a=1, i=4, get_i=get_i)
Klass2 = type('Klass2', (Super,), dct)
现在比较显示以下输出:
isinstance(Klass1.get_i, types.LambdaType) True
isinstance(Klass2.get_i, types.LambdaType) True
isinstance(Klass1.get_i, LambdaType) True
isinstance(Klass2.get_i, LambdaType) True
Klass1.get_i.__name__ get_i
Klass2.get_i.__name__ get_i
Klass1.get_i.__qualname__ Klass1.get_i
Klass2.get_i.__qualname__ Klass2.get_i
type(Klass1.get_i) <class 'function'>
type(Klass2.get_i) <class 'function'>
inspect.isfunction(Klass1.get_i) True
inspect.isfunction(Klass2.get_i) True
inspect.ismethod(Klass1.get_i) False
inspect.ismethod(Klass2.get_i) False