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>>
>>>