【发布时间】:2013-02-19 22:03:01
【问题描述】:
假设我有以下内容:
def func():
print 'this is a function and not a method!!!'
class Test:
def TestFunc(self):
print 'this is Test::TestFunc method'
我有以下函数(取自https://bitbucket.org/agronholm/apscheduler/src/d2f00d9ac019/apscheduler/util.py):
def get_callable_name(func):
"""
Returns the best available display name for the given function/callable.
"""
f_self = getattr(func, '__self__', None) or getattr(func, 'im_self', None)
if f_self and hasattr(func, '__name__'):
if isinstance(f_self, type):
# class method
clsname = getattr(f_self, '__qualname__', None) or f_self.__name__
return '%s.%s' % (clsname, func.__name__)
# bound method
return '%s.%s' % (f_self.__class__.__name__, func.__name__)
if hasattr(func, '__call__'):
if hasattr(func, '__name__'):
# function, unbound method or a class with a __call__ method
return func.__name__
# instance of a class with a __call__ method
return func.__class__.__name__
raise TypeError('Unable to determine a name for %s -- '
'maybe it is not a callable?' % repr(func))
def obj_to_ref(obj):
"""
Returns the path to the given object.
"""
ref = '%s:%s' % (obj.__module__, get_callable_name(obj))
try:
obj2 = ref_to_obj(ref)
if obj != obj2:
raise ValueError
except Exception:
raise ValueError('Cannot determine the reference to %s' % repr(obj))
return ref
def ref_to_obj(ref):
"""
Returns the object pointed to by ``ref``.
"""
if not isinstance(ref, basestring):
raise TypeError('References must be strings')
if not ':' in ref:
raise ValueError('Invalid reference')
modulename, rest = ref.split(':', 1)
try:
obj = __import__(modulename)
except ImportError:
raise LookupError('Error resolving reference %s: '
'could not import module' % ref)
try:
for name in modulename.split('.')[1:] + rest.split('.'):
obj = getattr(obj, name)
return obj
except Exception:
raise LookupError('Error resolving reference %s: '
'error looking up object' % ref)
上述函数 - obj_to_ref 返回给定函数对象的文本引用,ref_to_obj 返回给定文本引用的对象。例如,让我们试试func 函数。
>>>
>>> func
<function func at 0xb7704924>
>>>
>>> obj_to_ref(func)
'__main__:func'
>>>
>>> ref_to_obj('__main__:func')
<function func at 0xb7704924>
>>>
func 函数运行良好。但是当尝试在class Test 的实例上使用这些函数时,它无法获得文本参考。
>>>
>>> t = Test()
>>>
>>> t
<__main__.Test instance at 0xb771b28c>
>>>
>>> t.TestFunc
<bound method Test.TestFunc of <__main__.Test instance at 0xb771b28c>>
>>>
>>>
>>> obj_to_ref(t.TestFunc)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 11, in obj_to_ref
ValueError: Cannot determine the reference to <bound method Test.TestFunc of <__main__.Test instance at 0xb771b28c>>
>>>
>>>
给定输入t.TestFunc 的obj_to_ref 函数提供__main__:Test.TestFunc 作为文本表示,但不能使用相同的文本生成对象。
问题:
Python 中是否有一种方法可以表示像
>>> t.TestFunc
<bound method Test.TestFunc of <__main__.Test instance at 0xb771b28c>>
>>>
在字符串中并从字符串中重建对象?
如果我们将地址0xb771b28c保存为字符串的一部分并通过取消引用该地址重新生成对象,是否有可能?!
【问题讨论】:
-
实际用例是什么?你会用它做什么?至于实际重构:可以测试
eval('t.TestFunc')或者ref_to_obj('__main__:t.TestFunc') -
你好。
for name in modulename.split('.')[1:] + rest.split('.'):这条线应该怎么做?在您的代码中modulename.split('.')[1:]给出[ ] -
我认为问题出在
get_callable_name。get_callable_name(t.TestFunc)产生'Test.TestFunc'。这显然是错误的,因为它看起来像是指向类方法而不是绑定方法。 -
@entropy 如果
get_callable_name()为假,您必须证明该缺陷。我个人认为它没有缺陷。这就是为产生这种明显怪异的类实现的 Python 模型和函数。 -
@eyquem,如果您想将
t.TestFunc作为字符串的唯一路径,它应该是:'__main__:t.TestFunc'而不是'__main__:Test.TestFunc',这是get_callable_name的结果。如果您随后使用ref_to_obj解析从get_callable_name获得的结果,您将获得对未绑定类方法而不是绑定实例方法的引用。在下面的答案中检查我的代码,它确实有效,修复在get_callable_name
标签: python serialization pickle apscheduler