Python 方法的文本引用
假设我有以下几点:Python 方法的文本引用,python,serialization,pickle,apscheduler,Python,Serialization,Pickle,Apscheduler,假设我有以下几点: def func(): print 'this is a function and not a method!!!' class Test: def TestFunc(self): print 'this is Test::TestFunc method' 我有以下功能(摘自): 上述函数-obj_to_ref返回给定函数对象的文本引用,而ref_to_obj返回给定文本引用的对象。例如,让我们试试func函数 >>>
def func():
print 'this is a function and not a method!!!'
class Test:
def TestFunc(self):
print 'this is Test::TestFunc method'
我有以下功能(摘自):
上述函数-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>
>>>
给定输入t.TestFunc
的obj_to_ref
函数将\uuuuuu main\uuuuu:Test.TestFunc
作为文本表示,但不能使用相同的文本生成对象
问题:
在Python
中有没有一种方法可以表示这样的对象
>>> t.TestFunc
<bound method Test.TestFunc of <__main__.Test instance at 0xb771b28c>>
>>>
>t.TestFunc
>>>
在字符串中,并从字符串重建对象
如果我们将地址
0xb771b28c
保存为字符串的一部分,并通过取消引用此地址重新生成对象,是否可能 正如我在上面的评论中所说,问题在于get\u callable\u name
get\u callable\u name(t.TestFunc)
生成'Test.TestFunc'
,这显然是错误的。它应该是“t.TestFunc”。我在\u模块中添加了variable\u name\u,并在get\u callable\u name
中使用了它,现在代码开始工作了。底部的检查返回True
。然而,\u模块中的变量\u name\u非常粗糙,我找不到一种干净的方法来实现这一点
如果您只需要将其用于较小的内容,那么这应该没问题,但是请注意,variable\u name\u in\u module
中的get\u callable\u name
的每次调用都会导致N个字典查找,其中N是模块中的变量数
代码如下:
def variable_name_in_module(module, var):
for name in dir(module):
if getattr(module, name) == var:
return name
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' % (variable_name_in_module(__import__(f_self.__module__), f_self), 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)
class Test:
def TestFunc(self):
print "test"
t = Test()
print t.TestFunc == ref_to_obj(obj_to_ref(t.TestFunc))
编辑:PS:模块中的变量\u name\u如果找不到任何内容,可能会引发异常,尽管我不知道这是如何发生的。正如我在上面的评论中所说,问题在于获取可调用的\u name
get\u callable\u name(t.TestFunc)
生成'Test.TestFunc'
,这显然是错误的。它应该是“t.TestFunc”。我在\u模块中添加了variable\u name\u,并在get\u callable\u name
中使用了它,现在代码开始工作了。底部的检查返回True
。然而,\u模块中的变量\u name\u非常粗糙,我找不到一种干净的方法来实现这一点
如果您只需要将其用于较小的内容,那么这应该没问题,但是请注意,variable\u name\u in\u module
中的get\u callable\u name
的每次调用都会导致N个字典查找,其中N是模块中的变量数
代码如下:
def variable_name_in_module(module, var):
for name in dir(module):
if getattr(module, name) == var:
return name
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' % (variable_name_in_module(__import__(f_self.__module__), f_self), 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)
class Test:
def TestFunc(self):
print "test"
t = Test()
print t.TestFunc == ref_to_obj(obj_to_ref(t.TestFunc))
编辑:PS:模块中的变量\u name\u如果找不到任何内容,可能会引发异常,尽管我不知道这是如何发生的。您的问题很有趣,但很复杂
1) 您不应该调用func
get\u callable\u name(func)
在我的回答中,我将其替换为X
2) 你把代码的一部分放错地方了
try:
obj2 = ref_to_obj(ref)
print 'obj != obj2 : ',obj != obj2
if obj != obj2:
raise ValueError
except Exception:
raise ValueError('Cannot determine the reference to %s' % repr(obj))
return ref
在obj\u to\u ref()内没有任何关系
在我的回答中,我把它移到了这个函数之外
>>>
>>> func
<function func at 0xb7704924>
>>>
>>> obj_to_ref(func)
'__main__:func'
>>>
>>> ref_to_obj('__main__:func')
<function func at 0xb7704924>
>>>
3) 代码出现问题的明显原因是,为对象t.TestFunc
(在我的代码中传递到参数X
)获得的引用是”\uuu main\uuuuuuuu:Test.TestFunc'
,而不是“应该”的“\uu main\uuuuuuuuuu:t.TestFunc'
决定这一点的秘密步骤是在函数get\u callable\u name()
中,正如entropy所说的
因为f.self
是t
,X
有一个名称(TestFunc),但不是type
类型的类(因为t
是一个实例),
指令返回“%s.%s%”(f\u self.\u class\uuuuuu.\uuuu name\uuuuuuu,X.\uuuu name\uuuuuuu)
被执行
但是你把表达式f\u self.\uuuu class\uuuu.\uuuu name
:它是t
类的名称,而不是t
本身的名称。
问题在于,对于一个类(具有属性\uuuuuu name\uuuuu
)来说,Python语言中没有任何东西可以根据需要提供实例的名称:一个实例没有与类相同的属性\uuuuu name\uuuu
,而类会给出实例的名称
因此,由于不易获得,必须采用一种旁路。
每次需要一个未引用的名称时,旁路就是在名称空间的所有名称中搜索,并根据相关对象测试相应的对象。
这就是熵的函数获取可调用的\u name()
有了这个功能,它就工作了
但我想强调的是,这只是一个棘手的旁路,没有真正的基础。
我的意思是,该方法的名称t.TestFunc
是一种错觉。有一个微妙之处:没有属于实例的方法。这似乎是一种奇怪的伪装,但我相信这是事实。
事实上,我们之所以调用方法,是因为使用了类似于t.TestFunc
的表达式,这导致人们相信TestFunc
属于实例。实际上,它属于类,Python从一个实例到它的类来查找方法
我没有发明任何东西,我读过:
类实例有一个命名空间,该命名空间实现为
搜索属性引用的第一个位置。当
属性,并且实例的类具有
属性,则搜索将继续该类
属性。如果找到用户定义的类属性
函数对象或未绑定的用户定义方法对象
associated class是为其创建的实例的类(称为C)
属性引用已启动或其基础之一已启动
转换为绑定的用户定义的方法对象,其im_类
def get_callable_name(X):
"""
Returns the best available display name for the given function/callable.
"""
print '- inside get_callable_name()'
print ' object X arriving in get_callable_name() :\n ',X
f_self = getattr(X, '__self__', None) or getattr(X, 'im_self', None)
print ' X.__call__ ==',X.__call__
print ' X.__name__ ==',X.__name__
print '\n X.__self__== X.im_self ==',f_self
print ' isinstance(%r, type) is %r' % (f_self,isinstance(f_self, type))
if f_self and hasattr(X, '__name__'): # it is a method
if isinstance(f_self, type):
# class method
clsname = getattr(f_self, '__qualname__', None) or f_self.__name__
return '%s.%s' % (clsname, X.__name__)
# bound method
print '\n f_self.__class__ ==',f_self.__class__
print ' f_self.__class__.__name__ ==',f_self.__class__.__name__
return '%s.%s' % ('t', X.__name__)
if hasattr(X, '__call__'):
if hasattr(X, '__name__'):
# function, unbound method or a class with a __call__ method
return X.__name__
# instance of a class with a __call__ method
return X.__class__.__name__
raise TypeError('Unable to determine a name for %s -- '
'maybe it is not a callable?' % repr(X))
def obj_to_ref(obj):
"""
Returns the path to the given object.
"""
print '- obj arriving in obj_to_ref :\n %r' % obj
ref = '%s:%s' % (obj.__module__, get_callable_name(obj))
return ref
def ref_to_obj(ref):
"""
Returns the object pointed to by ``ref``.
"""
print '- ref arriving in ref_to_obj == %r' % 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)
print ' we start with dictionary obj == ',obj
try:
for name in modulename.split('.')[1:] + rest.split('.'):
print ' object of name ',name,' searched in',obj
obj = getattr(obj, name)
print ' got obj ==',obj
return obj
except Exception:
raise LookupError('Error resolving reference %s: '
'error looking up object' % ref)
class Test:
def TestFunc(self):
print 'this is Test::TestFunc method'
t = Test()
print 't ==',t
print '\nt.TestFunc ==',t.TestFunc
print "getattr(t,'TestFunc') ==",getattr(t,'TestFunc')
print ('\nTrying to obtain reference of t.TestFunc\n'
'----------------------------------------')
print '- REF = obj_to_ref(t.TestFunc) done'
REF = obj_to_ref(t.TestFunc)
print '\n- REF obtained: %r' % REF
print ("\n\nVerifying what is ref_to_obj(REF)\n"
"---------------------------------")
try:
print '- obj2 = ref_to_obj(REF) done'
obj2 = ref_to_obj(REF)
if obj2 != t.TestFunc:
raise ValueError
except Exception:
raise ValueError('Cannot determine the object of reference %s' % REF)
print '\n- object obtained : ',obj2
t == <__main__.Test instance at 0x011DF5A8>
t.TestFunc == <bound method Test.TestFunc of <__main__.Test instance at 0x011DF5A8>>
getattr(t,'TestFunc') == <bound method Test.TestFunc of <__main__.Test instance at 0x011DF5A8>>
Trying to obtain reference of t.TestFunc
----------------------------------------
- REF = obj_to_ref(t.TestFunc) done
- obj arriving in obj_to_ref :
<bound method Test.TestFunc of <__main__.Test instance at 0x011DF5A8>>
- inside get_callable_name()
object X arriving in get_callable_name() :
<bound method Test.TestFunc of <__main__.Test instance at 0x011DF5A8>>
X.__call__ == <method-wrapper '__call__' of instancemethod object at 0x011DB990>
X.__name__ == TestFunc
X.__self__== X.im_self == <__main__.Test instance at 0x011DF5A8>
isinstance(<__main__.Test instance at 0x011DF5A8>, type) is False
f_self.__class__ == __main__.Test
f_self.__class__.__name__ == Test
- REF obtained: '__main__:t.TestFunc'
Verifying what is ref_to_obj(REF)
---------------------------------
- obj2 = ref_to_obj(REF) done
- ref arriving in ref_to_obj == '__main__:t.TestFunc'
we start with dictionary obj == <module '__main__' (built-in)>
object of name t searched in <module '__main__' (built-in)>
got obj == <__main__.Test instance at 0x011DF5A8>
object of name TestFunc searched in <__main__.Test instance at 0x011DF5A8>
got obj == <bound method Test.TestFunc of <__main__.Test instance at 0x011DF5A8>>
- object obtained : <bound method Test.TestFunc of <__main__.Test instance at 0x011DF5A8>>
>>>