说我有以下几点:

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


给定输入obj_to_reft.TestFunc函数带有__main__:Test.TestFunc作为文本表示形式,但是不能使用相同的文本来生成对象。

题:

Python中有没有一种方法可以表示像

>>> t.TestFunc
<bound method Test.TestFunc of <__main__.Test instance at 0xb771b28c>>
>>>


在字符串中并从字符串中重建对象?

如果我们将地址0xb771b28c保存为字符串的一部分,并通过取消引用该地址来重新生成对象,这是否有可能?

最佳答案

您的问题很有趣但很纠结。

1)您不应将func的参数称为get_callable_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_to_ref()无关

在我的回答中,我将其移出了此功能。

3)代码问题的可见原因是为对象t.TestFunc(在我的代码中传递给参数X)获得的引用是'__main__:Test.TestFunc',而不是“应该”的'__main__:t.TestFunc'

决定这一点的秘密步骤在函数get_callable_name()中,如熵所言。
由于f.selft并且X具有名称(TestFunc)但不是type类型的类(因为t是实例),
指令return '%s.%s' % (f_self.__class__.__name__, X.__name__)被执行。

但是,将表达式f_self.__class__.__name放在您的位置是错误的:它是t类的名称,而不是t本身的名称。



问题在于,对于类(具有属性__name__的类)来说,Python语言中没有任何东西可以按需提供实例的名称:实例与类,它将给出实例的名称。

因此,不容易获得它,必须采用某种旁路。
每次需要一个未引用的名称时,绕过就是在名称空间的所有名称中搜索并针对相关对象测试相应的对象。
这就是熵函数__name__的作用。



使用此功能,它可以工作。

但我想强调,这只是一个棘手的旁路,没有真正的基础。
我的意思是该方法的名称get__callable_name()是一种幻觉。有一个微妙之处:没有方法属于一个实例。这似乎很奇怪,但是我敢肯定这是事实。
由于使用t.TestFunc之类的表达式来调用方法,这一事实导致人们相信t.TestFunc属于实例。实际上,它属于该类,而Python从实例进入其类以查找方法。

我什么都没发明,我已经读过了:


  一个类实例具有一个实现为字典的名称空间,该名称空间是
  搜索属性引用的第一位。当一个
  在那里找不到属性,并且实例的类具有
  该名称的属性,搜索继续到该类
  属性。如果找到用户定义的类属性
  函数对象或未绑定的用户定义方法对象,其
  关联类是为其实例的类(称为C)
  属性引用已启动或其基础之一,它是
  转换为绑定的用户定义方法对象,其im_class
  属性是C,其im_self属性是实例。
  
  http://docs.python.org/2/reference/datamodel.html#new-style-and-classic-classes


但是,好吧,这是我要争论的另一个故事,我没有时间参与。

只需验证以下几点:
尽管TestFunc给出了:
getattr(t,"TestFunc")
方法TestFunc不在<bound method Test.TestFunc of <__main__.Test instance at 0x011D8DC8>>的命名空间中:
t的结果是t.__dict__

我只想指出一点,因为函数{ }仅复制并模仿Python的明显行为和实现。
但是,实际的行为和内幕实现是不同的。



在下面的代码中,我通过使用istruction得到了很好的结果
get_callable_name()代替
return '%s.%s' % ('t', X.__name__)
return '%s.%s' % (f_self.__class__.__name__, func.__name__)
因为它实际上是功能return '%s.%s' % (variable_name_in_module(__import__(f_self.__module__), f_self), func.__name__)的功能(它不使用正常的过程,而是使用狡猾的方法)

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

关于python - 方法的文字引用,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14968349/

10-09 19:15