Skip to content

Commit 0b58dba

Browse files
author
yangwenqiang.ywq
committed
ast and inspect
Change-Id: I24204e8e861d4b964d41ca283fc5e95ce8bc4c7b
1 parent e74c71c commit 0b58dba

19 files changed

+1484
-3
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,10 @@ python的强大之处有很大的一方面在于它有各种各样非常强大
285285

286286
## [weakref](content/weakref.md)
287287

288+
## [ast](content/ast.md)
289+
290+
## [inspect](content/inspect.md)
291+
288292
## [tools](content/tools.md)
289293

290294
## [Other_thing](content/other_thing.md)

code/ast_back.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# coding=utf-8
2+
3+
import ast
4+
import unparse
5+
6+
code = """
7+
def add(a, b):
8+
return a + b
9+
10+
print add(1, 2)
11+
"""
12+
13+
14+
class CrazyTransformer(ast.NodeTransformer):
15+
16+
def visit_BinOp(self, node):
17+
node.op = ast.Mult()
18+
return node
19+
20+
21+
def back():
22+
module = ast.parse(code)
23+
transformer = CrazyTransformer()
24+
multi = transformer.visit(module)
25+
unparse.Unparser(multi)
26+
27+
28+
if __name__ == '__main__':
29+
back()

code/ast_change.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# coding=utf-8
2+
3+
import ast
4+
5+
6+
code = """
7+
def add(a, b):
8+
return a + b
9+
10+
print add(1, 2)
11+
"""
12+
13+
14+
class CrazyTransformer(ast.NodeTransformer):
15+
16+
def visit_BinOp(self, node):
17+
print node.__dict__
18+
node.op = ast.Mult()
19+
print node.__dict__
20+
return node
21+
22+
23+
def main():
24+
module = ast.parse(code)
25+
exec compile(module, '<string>', 'exec')
26+
transformer = CrazyTransformer()
27+
multi = transformer.visit(module)
28+
exec compile(multi, '<string>', 'exec')
29+
30+
31+
if __name__ == '__main__':
32+
main()

code/ast_demo.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# coding=utf-8
2+
3+
import ast
4+
5+
code = """
6+
def add(a, b):
7+
return a + b
8+
9+
add(1, 2)
10+
"""
11+
12+
print "hello world"
13+
print ast.parse(code)
14+
print ast.dump(ast.parse(code))

code/ast_other.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# coding=utf-8
2+
3+
import ast
4+
import codegen
5+
import astunparse
6+
import astor
7+
8+
9+
code = """
10+
data = {
11+
"key": "value",
12+
"list": [1,2,3]
13+
}
14+
15+
def add(a, b):
16+
return a + b
17+
18+
print add(1, 2)
19+
"""
20+
21+
module = ast.parse(code)
22+
23+
print codegen.to_source(module)
24+
print astunparse.unparse(module)
25+
print astor.to_source(module)

code/bunch.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,17 @@ if __name__ == '__main__':
8989

9090
基本上是一个思路,然后再加了一些捕获异常和类型转换,更容易的转换为其他的数据结构。
9191

92+
93+
还可以这样
94+
95+
```
96+
class Namespace(dict):
97+
def __getattr__(self, name):
98+
try:
99+
return self[name]
100+
except KeyError:
101+
raise AttributeError(name)
102+
103+
def __setattr__(self, name, value):
104+
self[name] = value
105+
```

code/example.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# coding=utf-8
2+
# 只能这里么?
3+
4+
5+
# fist two line comment
6+
# 再来一行注释
7+
8+
functions = {}
9+
10+
def add(a, b):
11+
return a + b
12+
13+
14+
class A(object):
15+
"""
16+
A class
17+
"""
18+
def ___init__(self, name):
19+
self.name = name
20+
21+
22+
class B(A):
23+
24+
def hello(self, word=None):
25+
"""
26+
greeting
27+
"""
28+
if not word:
29+
word = self.name
30+
print "hello {}".format(word)
31+
32+
33+
a = A()
34+
b = B()

code/inspect_args.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# coding=utf-8
2+
3+
import inspect
4+
import example
5+
6+
7+
def main(a=1):
8+
print inspect.getargvalues(inspect.currentframe())
9+
10+
11+
if __name__ == '__main__':
12+
main()
13+
print inspect.getargspec(example.add)
14+
print inspect.formatargspec(inspect.getargspec(example.add))
15+
print inspect.getargspec(example.B.hello)
16+
print inspect.getcallargs(example.add, 1, 2)
17+
print inspect.getcallargs(example.B.hello, self=None, word="world")

code/inspect_class_and_instant.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# coding=utf-8
2+
3+
import inspect
4+
import example
5+
6+
7+
def detect_class():
8+
print("A:")
9+
for name, data in inspect.getmembers(example.A):
10+
print('{} : {}'.format(name, data))
11+
12+
13+
def detect_method():
14+
print("A:")
15+
for name, data in inspect.getmembers(example.A, inspect.ismethod):
16+
print('{} : {}'.format(name, data))
17+
print("B:")
18+
for name, data in inspect.getmembers(example.B, inspect.ismethod):
19+
print('{} : {}'.format(name, data))
20+
print("a:")
21+
for name, data in inspect.getmembers(example.a, inspect.ismethod):
22+
print('{} : {}'.format(name, data))
23+
24+
25+
if __name__ == '__main__':
26+
detect_class()
27+
detect_method()

code/inspect_demo.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# coding=utf-8
2+
3+
import inspect
4+
5+
import example
6+
7+
8+
def detect_all():
9+
for name, data in inspect.getmembers(example):
10+
if name.startswith('__'):
11+
continue
12+
print('{} : {}'.format(name, data))
13+
14+
15+
def detect_class():
16+
for name, data in inspect.getmembers(example, inspect.isclass):
17+
if name.startswith('__'):
18+
continue
19+
print('{} : {}'.format(name, data))
20+
21+
22+
def detect_code():
23+
for name, data in inspect.getmembers(example, inspect.iscode):
24+
if name.startswith('__'):
25+
continue
26+
print('{} : {}'.format(name, data))
27+
28+
29+
def detect_function():
30+
for name, data in inspect.getmembers(example, inspect.isfunction):
31+
if name.startswith('__'):
32+
continue
33+
print('{} : {}'.format(name, data))
34+
35+
36+
if __name__ == '__main__':
37+
print "all:"
38+
detect_all()
39+
print "class:"
40+
detect_class()
41+
print "function:"
42+
detect_function()
43+
print "code:"
44+
detect_code()

code/inspect_detect.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# coding=utf-8
2+
3+
import inspect
4+
import example
5+
6+
if __name__ == '__main__':
7+
print inspect.isbuiltin(apply)
8+
print inspect.isbuiltin(lambda: None)
9+
print inspect.isclass(type)
10+
print inspect.isclass(1)
11+
print inspect.iscode(example.add.func_code)
12+
print inspect.iscode(example.B.hello.im_func.func_code)
13+
print inspect.iscode("1+1")
14+
print inspect.ismodule(inspect)
15+
print inspect.isfunction(input)
16+
print inspect.isgenerator(iter([]))
17+
print inspect.isgenerator([])

code/inspect_source.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# coding=utf-8
2+
3+
import inspect
4+
import example
5+
6+
if __name__ == '__main__':
7+
8+
print inspect.getcomments(example)
9+
print inspect.getdoc(example)
10+
print inspect.getdoc(example.A)
11+
print inspect.getdoc(example.B.hello)
12+
13+
print inspect.findsource(example.A)
14+
15+
print inspect.getabsfile(example.A)
16+
print inspect.getfile(example.A)
17+
print inspect.getsource(example)
18+
print inspect.getsource(example.A)
19+
print inspect.getsourcefile(example.A)
20+
print inspect.getsourcelines(example.A)
21+
22+
print inspect.getmodule(example.A)
23+
print inspect.getmoduleinfo("example.py")
24+
print inspect.getmodulename("example.py")

code/inspect_stack.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# coding=utf-8
2+
3+
import inspect
4+
5+
6+
def get_frame():
7+
"""
8+
帧是当前的上下文,调用时的环境变量和数据
9+
"""
10+
frame = inspect.currentframe()
11+
print 'line {} of {}'.format(frame.f_lineno, frame.f_code.co_filename)
12+
print 'locals: {}'.format(frame.f_locals)
13+
14+
15+
def get_stack():
16+
"""
17+
栈是用来展示调用链路,每一层都是一个帧
18+
"""
19+
for frame, filename, lineno, func, code_context, code_index in inspect.stack():
20+
print('{}[{}]\n -> {}:{}'.format(
21+
filename,
22+
lineno,
23+
func,
24+
code_context[code_index].strip()
25+
))
26+
print frame.f_locals
27+
28+
29+
if __name__ == '__main__':
30+
frame = inspect.currentframe()
31+
print 'line {} of {}'.format(frame.f_lineno, frame.f_code.co_filename)
32+
print 'locals: {}'.format(frame.f_locals)
33+
34+
get_frame()
35+
get_stack()

code/marshmallow_demo.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,25 @@ class AlbumSchema(Schema):
1414
title = fields.Str()
1515
release_date = fields.Date()
1616
artist = fields.Nested(ArtistSchema())
17+
response = fields.Function(serialize=lambda x: "response data")
18+
request = fields.Function(serialize=lambda x:x.a, deserialize=lambda x: "request data")
1719

1820

1921
bowie = dict(name='David Bowie', location=["Beijing", "Shanghai"])
20-
album = dict(artist=bowie, title="Hunky Dory", release_date=datetime.now())
22+
album = dict(artist=bowie, title="Hunky Dory", release_date=datetime.now(), request="...")
2123

2224
schema = AlbumSchema()
23-
result = schema.dump(album)
24-
pprint(result, indent=2)
2525

26+
# 将一个 object 转换成 dict , 属于 serialize 在 pack response 中
27+
# 在转换成 dict 的时候,会去取值,如果没有,就会返回 missing_, 然后再返回值里也不展示
28+
dump_result = schema.dump(album)
29+
pprint(dump_result, indent=2)
30+
print dump_result.data
31+
32+
# 讲一个 dict 转换成 object, 属于 deserialize 在 request 里或者 转化里使用
33+
# 使用 load 的时候,原始数据中必须存在这个字段,如果原始字段不存在,则没有,如果没有 deserialize 函数,则返回原始值。
34+
load_result = schema.load(album)
35+
pprint(load_result, indent=2)
36+
print load_result.data
37+
38+
# print schema.fields

0 commit comments

Comments
 (0)