python 的注释(例如数据类)可以扩展到它生成的代码中吗?
Can python's annotation (e.g dataclass) be expanded into the code it produces?
我在 python 还是个业余爱好者。
是否可以查看 python 的注释扩展到什么?
例如,与数据类相关的错误,有时试图找出它实际生成的代码有点棘手。
例如:
@dataclass(order = True)
class Person:
name: str
age:int = 0
==
class Person:
def __init__(self, name:str, age=0):
self.name = name
self.age = age
def __repr__...
def __eq__(self, other):
return (self.name, self.age) == ( other.name, other.age)
或者如果不可能,除了检查注释源代码之外,您通常如何弄清楚它们扩展到什么?
例如,Racket 有一个强大的扩展宏的机制,python 有类似的东西吗?
恐怕无法按您的意愿显示代码,因为数据class 修饰是运行时更改。您可以做的最好的事情是使用 inspect.getsource,它将显示原始的 class,不幸的是没有数据 class 更改:
>>> inspect.getsource(Person)
class Person:
name: str
age:int = 0
虽然您的问题的答案是 "It's not possible",但也许以下内容可以帮助您。给定 Person
这是您的数据 class,而 SimplePerson
与没有数据 class 修饰的 Person
完全相同:
dir - 在运行时获取对象的属性(包括方法)
>>> dir(SimplePerson)
['__annotations__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__',
'__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__',
'__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__',
'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__',
'__str__', '__subclasshook__', '__weakref__', 'age']
# looks just like a base object, plus 'age', which was not only declared, but also set
>>> dir(Person)
['__annotations__', '__class__', '__dataclass_fields__', '__dataclass_params__',
'__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__',
'__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__',
'__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__',
'age']
# has some more attributes and methods that the dataclass decoration added
dis.dis - 将对象的方法反汇编成字节码
>>> import dis
>>> dis.dis(SimplePerson)
# no output, there are no methods on an object that only has two class attributes
>>> import dis
>>> dis.dis(Person)
Disassembly of __eq__:
2 0 LOAD_FAST 1 (other)
2 LOAD_ATTR 0 (__class__)
4 LOAD_FAST 0 (self)
6 LOAD_ATTR 0 (__class__)
8 COMPARE_OP 8 (is)
10 POP_JUMP_IF_FALSE 36
3 12 LOAD_FAST 0 (self)
14 LOAD_ATTR 1 (name)
16 LOAD_FAST 0 (self)
18 LOAD_ATTR 2 (age)
20 BUILD_TUPLE 2
22 LOAD_FAST 1 (other)
24 LOAD_ATTR 1 (name)
26 LOAD_FAST 1 (other)
28 LOAD_ATTR 2 (age)
30 BUILD_TUPLE 2
32 COMPARE_OP 2 (==)
34 RETURN_VALUE
4 >> 36 LOAD_GLOBAL 3 (NotImplemented)
38 RETURN_VALUE
Disassembly of __ge__:
2 0 LOAD_FAST 1 (other)
2 LOAD_ATTR 0 (__class__)
4 LOAD_FAST 0 (self)
6 LOAD_ATTR 0 (__class__)
8 COMPARE_OP 8 (is)
10 POP_JUMP_IF_FALSE 36
3 12 LOAD_FAST 0 (self)
14 LOAD_ATTR 1 (name)
16 LOAD_FAST 0 (self)
18 LOAD_ATTR 2 (age)
20 BUILD_TUPLE 2
22 LOAD_FAST 1 (other)
24 LOAD_ATTR 1 (name)
26 LOAD_FAST 1 (other)
28 LOAD_ATTR 2 (age)
30 BUILD_TUPLE 2
32 COMPARE_OP 5 (>=)
34 RETURN_VALUE
4 >> 36 LOAD_GLOBAL 3 (NotImplemented)
38 RETURN_VALUE
Disassembly of __gt__:
2 0 LOAD_FAST 1 (other)
2 LOAD_ATTR 0 (__class__)
4 LOAD_FAST 0 (self)
6 LOAD_ATTR 0 (__class__)
8 COMPARE_OP 8 (is)
10 POP_JUMP_IF_FALSE 36
3 12 LOAD_FAST 0 (self)
14 LOAD_ATTR 1 (name)
16 LOAD_FAST 0 (self)
18 LOAD_ATTR 2 (age)
20 BUILD_TUPLE 2
22 LOAD_FAST 1 (other)
24 LOAD_ATTR 1 (name)
26 LOAD_FAST 1 (other)
28 LOAD_ATTR 2 (age)
30 BUILD_TUPLE 2
32 COMPARE_OP 4 (>)
34 RETURN_VALUE
4 >> 36 LOAD_GLOBAL 3 (NotImplemented)
38 RETURN_VALUE
Disassembly of __init__:
2 0 LOAD_FAST 1 (name)
2 LOAD_FAST 0 (self)
4 STORE_ATTR 0 (name)
3 6 LOAD_FAST 2 (age)
8 LOAD_FAST 0 (self)
10 STORE_ATTR 1 (age)
12 LOAD_CONST 0 (None)
14 RETURN_VALUE
Disassembly of __le__:
2 0 LOAD_FAST 1 (other)
2 LOAD_ATTR 0 (__class__)
4 LOAD_FAST 0 (self)
6 LOAD_ATTR 0 (__class__)
8 COMPARE_OP 8 (is)
10 POP_JUMP_IF_FALSE 36
3 12 LOAD_FAST 0 (self)
14 LOAD_ATTR 1 (name)
16 LOAD_FAST 0 (self)
18 LOAD_ATTR 2 (age)
20 BUILD_TUPLE 2
22 LOAD_FAST 1 (other)
24 LOAD_ATTR 1 (name)
26 LOAD_FAST 1 (other)
28 LOAD_ATTR 2 (age)
30 BUILD_TUPLE 2
32 COMPARE_OP 1 (<=)
34 RETURN_VALUE
4 >> 36 LOAD_GLOBAL 3 (NotImplemented)
38 RETURN_VALUE
Disassembly of __lt__:
2 0 LOAD_FAST 1 (other)
2 LOAD_ATTR 0 (__class__)
4 LOAD_FAST 0 (self)
6 LOAD_ATTR 0 (__class__)
8 COMPARE_OP 8 (is)
10 POP_JUMP_IF_FALSE 36
3 12 LOAD_FAST 0 (self)
14 LOAD_ATTR 1 (name)
16 LOAD_FAST 0 (self)
18 LOAD_ATTR 2 (age)
20 BUILD_TUPLE 2
22 LOAD_FAST 1 (other)
24 LOAD_ATTR 1 (name)
26 LOAD_FAST 1 (other)
28 LOAD_ATTR 2 (age)
30 BUILD_TUPLE 2
32 COMPARE_OP 0 (<)
34 RETURN_VALUE
4 >> 36 LOAD_GLOBAL 3 (NotImplemented)
38 RETURN_VALUE
Disassembly of __repr__:
352 0 LOAD_GLOBAL 0 (id)
2 LOAD_FAST 0 (self)
4 CALL_FUNCTION 1
6 LOAD_GLOBAL 1 (_thread)
8 LOAD_METHOD 2 (get_ident)
10 CALL_METHOD 0
12 BUILD_TUPLE 2
14 STORE_FAST 1 (key)
353 16 LOAD_FAST 1 (key)
18 LOAD_DEREF 0 (repr_running)
20 COMPARE_OP 6 (in)
22 POP_JUMP_IF_FALSE 28
354 24 LOAD_CONST 1 ('...')
26 RETURN_VALUE
355 >> 28 LOAD_DEREF 0 (repr_running)
30 LOAD_METHOD 3 (add)
32 LOAD_FAST 1 (key)
34 CALL_METHOD 1
36 POP_TOP
356 38 SETUP_FINALLY 12 (to 52)
357 40 LOAD_DEREF 1 (user_function)
42 LOAD_FAST 0 (self)
44 CALL_FUNCTION 1
46 STORE_FAST 2 (result)
48 POP_BLOCK
50 LOAD_CONST 0 (None)
359 >> 52 LOAD_DEREF 0 (repr_running)
54 LOAD_METHOD 4 (discard)
56 LOAD_FAST 1 (key)
58 CALL_METHOD 1
60 POP_TOP
62 END_FINALLY
360 64 LOAD_FAST 2 (result)
66 RETURN_VALUE
# not exactly readable, but here it is.. the code that dataclass added.
我在 python 还是个业余爱好者。
是否可以查看 python 的注释扩展到什么? 例如,与数据类相关的错误,有时试图找出它实际生成的代码有点棘手。
例如:
@dataclass(order = True)
class Person:
name: str
age:int = 0
==
class Person:
def __init__(self, name:str, age=0):
self.name = name
self.age = age
def __repr__...
def __eq__(self, other):
return (self.name, self.age) == ( other.name, other.age)
或者如果不可能,除了检查注释源代码之外,您通常如何弄清楚它们扩展到什么?
例如,Racket 有一个强大的扩展宏的机制,python 有类似的东西吗?
恐怕无法按您的意愿显示代码,因为数据class 修饰是运行时更改。您可以做的最好的事情是使用 inspect.getsource,它将显示原始的 class,不幸的是没有数据 class 更改:
>>> inspect.getsource(Person)
class Person:
name: str
age:int = 0
虽然您的问题的答案是 "It's not possible",但也许以下内容可以帮助您。给定 Person
这是您的数据 class,而 SimplePerson
与没有数据 class 修饰的 Person
完全相同:
dir - 在运行时获取对象的属性(包括方法)
>>> dir(SimplePerson)
['__annotations__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__',
'__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__',
'__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__',
'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__',
'__str__', '__subclasshook__', '__weakref__', 'age']
# looks just like a base object, plus 'age', which was not only declared, but also set
>>> dir(Person)
['__annotations__', '__class__', '__dataclass_fields__', '__dataclass_params__',
'__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__',
'__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__',
'__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__',
'age']
# has some more attributes and methods that the dataclass decoration added
dis.dis - 将对象的方法反汇编成字节码
>>> import dis
>>> dis.dis(SimplePerson)
# no output, there are no methods on an object that only has two class attributes
>>> import dis
>>> dis.dis(Person)
Disassembly of __eq__:
2 0 LOAD_FAST 1 (other)
2 LOAD_ATTR 0 (__class__)
4 LOAD_FAST 0 (self)
6 LOAD_ATTR 0 (__class__)
8 COMPARE_OP 8 (is)
10 POP_JUMP_IF_FALSE 36
3 12 LOAD_FAST 0 (self)
14 LOAD_ATTR 1 (name)
16 LOAD_FAST 0 (self)
18 LOAD_ATTR 2 (age)
20 BUILD_TUPLE 2
22 LOAD_FAST 1 (other)
24 LOAD_ATTR 1 (name)
26 LOAD_FAST 1 (other)
28 LOAD_ATTR 2 (age)
30 BUILD_TUPLE 2
32 COMPARE_OP 2 (==)
34 RETURN_VALUE
4 >> 36 LOAD_GLOBAL 3 (NotImplemented)
38 RETURN_VALUE
Disassembly of __ge__:
2 0 LOAD_FAST 1 (other)
2 LOAD_ATTR 0 (__class__)
4 LOAD_FAST 0 (self)
6 LOAD_ATTR 0 (__class__)
8 COMPARE_OP 8 (is)
10 POP_JUMP_IF_FALSE 36
3 12 LOAD_FAST 0 (self)
14 LOAD_ATTR 1 (name)
16 LOAD_FAST 0 (self)
18 LOAD_ATTR 2 (age)
20 BUILD_TUPLE 2
22 LOAD_FAST 1 (other)
24 LOAD_ATTR 1 (name)
26 LOAD_FAST 1 (other)
28 LOAD_ATTR 2 (age)
30 BUILD_TUPLE 2
32 COMPARE_OP 5 (>=)
34 RETURN_VALUE
4 >> 36 LOAD_GLOBAL 3 (NotImplemented)
38 RETURN_VALUE
Disassembly of __gt__:
2 0 LOAD_FAST 1 (other)
2 LOAD_ATTR 0 (__class__)
4 LOAD_FAST 0 (self)
6 LOAD_ATTR 0 (__class__)
8 COMPARE_OP 8 (is)
10 POP_JUMP_IF_FALSE 36
3 12 LOAD_FAST 0 (self)
14 LOAD_ATTR 1 (name)
16 LOAD_FAST 0 (self)
18 LOAD_ATTR 2 (age)
20 BUILD_TUPLE 2
22 LOAD_FAST 1 (other)
24 LOAD_ATTR 1 (name)
26 LOAD_FAST 1 (other)
28 LOAD_ATTR 2 (age)
30 BUILD_TUPLE 2
32 COMPARE_OP 4 (>)
34 RETURN_VALUE
4 >> 36 LOAD_GLOBAL 3 (NotImplemented)
38 RETURN_VALUE
Disassembly of __init__:
2 0 LOAD_FAST 1 (name)
2 LOAD_FAST 0 (self)
4 STORE_ATTR 0 (name)
3 6 LOAD_FAST 2 (age)
8 LOAD_FAST 0 (self)
10 STORE_ATTR 1 (age)
12 LOAD_CONST 0 (None)
14 RETURN_VALUE
Disassembly of __le__:
2 0 LOAD_FAST 1 (other)
2 LOAD_ATTR 0 (__class__)
4 LOAD_FAST 0 (self)
6 LOAD_ATTR 0 (__class__)
8 COMPARE_OP 8 (is)
10 POP_JUMP_IF_FALSE 36
3 12 LOAD_FAST 0 (self)
14 LOAD_ATTR 1 (name)
16 LOAD_FAST 0 (self)
18 LOAD_ATTR 2 (age)
20 BUILD_TUPLE 2
22 LOAD_FAST 1 (other)
24 LOAD_ATTR 1 (name)
26 LOAD_FAST 1 (other)
28 LOAD_ATTR 2 (age)
30 BUILD_TUPLE 2
32 COMPARE_OP 1 (<=)
34 RETURN_VALUE
4 >> 36 LOAD_GLOBAL 3 (NotImplemented)
38 RETURN_VALUE
Disassembly of __lt__:
2 0 LOAD_FAST 1 (other)
2 LOAD_ATTR 0 (__class__)
4 LOAD_FAST 0 (self)
6 LOAD_ATTR 0 (__class__)
8 COMPARE_OP 8 (is)
10 POP_JUMP_IF_FALSE 36
3 12 LOAD_FAST 0 (self)
14 LOAD_ATTR 1 (name)
16 LOAD_FAST 0 (self)
18 LOAD_ATTR 2 (age)
20 BUILD_TUPLE 2
22 LOAD_FAST 1 (other)
24 LOAD_ATTR 1 (name)
26 LOAD_FAST 1 (other)
28 LOAD_ATTR 2 (age)
30 BUILD_TUPLE 2
32 COMPARE_OP 0 (<)
34 RETURN_VALUE
4 >> 36 LOAD_GLOBAL 3 (NotImplemented)
38 RETURN_VALUE
Disassembly of __repr__:
352 0 LOAD_GLOBAL 0 (id)
2 LOAD_FAST 0 (self)
4 CALL_FUNCTION 1
6 LOAD_GLOBAL 1 (_thread)
8 LOAD_METHOD 2 (get_ident)
10 CALL_METHOD 0
12 BUILD_TUPLE 2
14 STORE_FAST 1 (key)
353 16 LOAD_FAST 1 (key)
18 LOAD_DEREF 0 (repr_running)
20 COMPARE_OP 6 (in)
22 POP_JUMP_IF_FALSE 28
354 24 LOAD_CONST 1 ('...')
26 RETURN_VALUE
355 >> 28 LOAD_DEREF 0 (repr_running)
30 LOAD_METHOD 3 (add)
32 LOAD_FAST 1 (key)
34 CALL_METHOD 1
36 POP_TOP
356 38 SETUP_FINALLY 12 (to 52)
357 40 LOAD_DEREF 1 (user_function)
42 LOAD_FAST 0 (self)
44 CALL_FUNCTION 1
46 STORE_FAST 2 (result)
48 POP_BLOCK
50 LOAD_CONST 0 (None)
359 >> 52 LOAD_DEREF 0 (repr_running)
54 LOAD_METHOD 4 (discard)
56 LOAD_FAST 1 (key)
58 CALL_METHOD 1
60 POP_TOP
62 END_FINALLY
360 64 LOAD_FAST 2 (result)
66 RETURN_VALUE
# not exactly readable, but here it is.. the code that dataclass added.