class A(object):
def m(self):
print self.x + self.y + self.z()
有沒有一種方法來查詢:
self_attributes_referenced(A.m) #=> ['x', 'y']
沒有做反編譯或解析?
是否有相應的方法來調用自我方法?
self_methods_referenced(A.m) #=> ['z']
class A(object):
def m(self):
print self.x + self.y + self.z()
有沒有一種方法來查詢:
self_attributes_referenced(A.m) #=> ['x', 'y']
沒有做反編譯或解析?
是否有相應的方法來調用自我方法?
self_methods_referenced(A.m) #=> ['z']
像這樣的東西應該工作:
import inspect
class Referee(object):
def __getattribute__(self, name):
attr = object.__getattribute__(self, name)
if inspect.ismethod(attr):
try:
meths_referenced = object.__getattribute__(
self, 'meths_referenced')
except AttributeError:
meths_referenced = set()
object.__setattr__(self, 'meths_referenced', meths_referenced)
meths_referenced.add(name)
else:
try:
attrs_referenced = object.__getattribute__(
self, 'attrs_referenced')
except AttributeError:
attrs_referenced = set()
object.__setattr__(self, 'attrs_referenced', attrs_referenced)
attrs_referenced.add(name)
return attr
def attributes_referenced(obj):
try:
return object.__getattribute__(obj, 'attrs_referenced')
except AttributeError:
return set()
def methods_referenced(obj):
try:
return object.__getattribute__(obj, 'meths_referenced')
except AttributeError:
return set()
class A(Referee):
def __init__(self):
self.x = 1
self.y = 2
def z(self):
return 3
def m(self):
print self.x + self.y + self.z()
a = A()
a.m()
print attributes_referenced(a)
print methods_referenced(a)
此打印:
6
set(['y', 'x'])
set(['z', 'm'])
繼承Referee
,每當你想提供此功能。 爲什麼你需要這個功能超出了我的理解。 =)
這可能是我見過的最痛苦的事情。感謝你擁有意志力,甚至寫下它。 –
在這個問題中,您將解析排除爲解決方案,但您是否意識到使用ast module解析和修改Python源代碼是多麼容易?
首先定義一個NodeTransformer
:
import ast
class RecordReferencesTransformer(ast.NodeTransformer):
def visit_FunctionDef(self, node):
def is_attr_on_self(n):
return type(n) is ast.Attribute and type(n.value) is ast.Name and n.value.id == 'self'
targets = [ast.Attribute(value=ast.Name(id=node.name, ctx=ast.Load()), attr='self_attributes_referenced', ctx=ast.Store())]
attrs = [n.attr for n in ast.walk(node) if is_attr_on_self(n)]
value = ast.Tuple(elts=[ast.Str(s=attr) for attr in attrs], ctx=ast.Load())
return [node, ast.Assign(targets=targets, value=value)]
然後而不是直接使用import
加載我們的模塊,我們需要一點額外的樣板在我們NodeTransformer
勻場:
filename = 'program.py'
parsed = ast.parse(open(filename).read())
with_references = RecordReferencesTransformer().visit(parsed)
ast.fix_missing_locations(with_references)
exec compile(with_references, filename, 'exec')
print A.m.self_attributes_referenced
a = A()
a.m()
輸出:
('x', 'y')
3
實施self_methods_referenced
作爲練習留給讀者。
最後,program.py
來源:
class A(object):
x, y = 1, 2
def m(self):
print self.x + self.y
真不可思議。你甚至不需要**運行** A()和a.m()。 「打印A.m.self_attributes_referenced」就足夠了。 –
@ A.JesseJiryuDavis true!我重新安排了陳述以說明這一點 –
我來使用''dis''模塊最接近的一次。但是,這將需要一些我沒有時間的輸出解析:/ –
目前尚不清楚你正在嘗試做什麼。您是否試圖找到一種方法來查看屬性是否已設置/使用/查看,並且方法相同?或者是其他東西? – Aidan
這似乎是一件奇怪的事情想要做。首先,它通過一個你通常不應該嘲笑的抽象障礙。另一方面,它不會像你期望的那樣告訴你。考慮'def method(self):return self .__ helper_that_does_all_the_work()'。誰知道這是什麼? – user2357112