代码之家  ›  专栏  ›  技术社区  ›  tel

在Python中访问实例名称以进行打印

  •  2
  • tel  · 技术社区  · 14 年前

    因此,作为“像计算机科学家一样思考”问题17.6的一部分,我写了一个名为“袋鼠”的课程:

    class Kangaroo(object):
    
        def __init__(self, pouch_contents = []):
            self.pouch_contents = pouch_contents
    
        def __str__(self):
            '''
            >>> kanga = Kangaroo()
            >>> kanga.put_in_pouch('olfactory')
            >>> kanga.put_in_pouch(7)
            >>> kanga.put_in_pouch(8)
            >>> kanga.put_in_pouch(9)
            >>> print kanga
            "In kanga's pouch there is: ['olfactory', 7, 8, 9]"
            '''
    
            return "In %s's pouch there is: %s" % (object.__str__(self), self.pouch_contents)
    
        def put_in_pouch(self, other):
            '''
            >>> kanga = Kangaroo()
            >>> kanga.put_in_pouch('olfactory')
            >>> kanga.put_in_pouch(7)
            >>> kanga.put_in_pouch(8)
            >>> kanga.put_in_pouch(9)
            >>> kanga.pouch_contents
            ['olfactory', 7, 8, 9]
            '''
    
            self.pouch_contents.append(other)
    

    让我发疯的是,我希望能够编写一个字符串方法,通过下面的单元测试 __str__ 如前所述。我现在得到的是:

    In <__main__.Kangaroo object at 0x4dd870>'s pouch there is: ['olfactory', 7, 8, 9]
    

    基本上,我想知道的是,是否有一些函数可以在kanga=Kangaroo上执行,这样函数的输出就是这5个字符,即函数(kanga)->“kanga”。

    有什么想法吗?

    阅读第一个答案让我意识到有一种更简洁的方式来问我原来的问题。有办法重写吗 __init__ 这样下面的代码是有效的吗?

    >>> somename = Kangaroo()
    >>> somename.name
    'somename'
    
    5 回复  |  直到 12 年前
        1
  •  2
  •   aaronasterling    14 年前

    我不打算发布这个,但如果你只想调试这个,那么给你:

    import sys
    
    class Kangaroo(object):
        def __str__(self):
            flocals = sys._getframe(1).f_locals
            for ident in flocals:
                if flocals[ident] is self:
                    name = ident
                    break
            else:   
                name = 'roo'
            return "in {0}'s pouch, there is {1}".format(name, self.pouch_contents)
    
    kang = Kangaroo()
    print kang
    

    这依赖于CPython(AFAIK),不适用于生产代码。如果实例在任何类型的容器中,它都不会工作,并且可能在任何时候由于任何原因而失败。不过,它应该对你有用。

    它的工作原理是 f_locals print kang 本地人 是框架中变量的名称,所以我们只需循环遍历它并测试每个条目是否正确 self break . 如果 打破 如果没有执行,那么我们就没有找到条目和循环 else

    如果你想把它从某种容器中拿出来,你需要扩展它来查看容器中的任何容器 . 如果是dictlike容器,则可以返回键;如果是元组或列表,则可以返回索引。

        2
  •  6
  •   John Machin Santi    14 年前

    要将您的请求放到透视图中,请解释您希望将哪个名称附加到由此代码创建的对象上:

    marsupials = []
    marsupials.append(Kangaroo()) 
    

    This classic essay by the effbot

    回答编辑中修改过的问题:否。

    在Python的CPython实现中,至少在任何给定的时间,所有现有对象都有一个惟一的ID,可以通过 id(obj) . 这对于您的调试目的可能已经足够了。注意,如果删除了一个对象,那么这个ID(内存地址)可以被随后创建的对象重用。

        3
  •  2
  •   John La Rooy    14 年前
    class Kangaroo(object):
    
        def __init__(self, pouch_contents=None, name='roo'):
            if pouch_contents is None:
                self.pouch_contents = []  # this isn't shared with all other instances
            else:
                self.pouch_contents = pouch_contents
            self.name = name
        ...
    
    kanga = Kangaroo(name='kanga')
    

    请注意,这是一个很好的风格 在周围放置空格 = 在争论中

        4
  •  0
  •   Ivo van der Wijk    14 年前

    在Python中,您想要的基本上是不可能的,即使使用建议的“hack”。例如,

    >>> kanga1 = kanga2 = kanga3 = Kangaroo()
    >>> kanga2.name 
    ???
    >>> kanga3.name
    ???
    

    >>> l = [Kangaroo()]
    >>> l[0].name
    ???
    

    如果需要“命名”对象,只需为对象提供一个名称即可

    def __init__(self, name):
        self.name = name
    

    更显式(我们喜欢Python)并且在所有情况下都是一致的。当然你可以做一些像

    >>> foo = Kangaroo("bar")
    >>> foo.name
    'bar'
    

    但foo将只是实例可能拥有的众多标签之一。名称是明确的和永久的。如果需要,您甚至可以强制使用唯一命名(同时您可以对不同的对象重复使用变量)

        5
  •  0
  •   tel    14 年前

    class Kangaroo(object):
    
        def __init__(self, pouch_contents = ()):
            self.pouch_contents = list(pouch_contents)
    
        def __str__(self):
            if not hasattr(self, 'name'):
                for k, v in globals().iteritems():
                    if id(v) == id(self):
                        self.name = k
                        break
                    else:
                        self.name = 'roo'                    
            return "In %s's pouch there is: %s" % (self.name, self.pouch_contents)
    
    kanga = Kangaroo()
    print kanga
    

    你可以通过搞笑的方式来打破这一点(它的工作原理和写的一样,但是作为doctest的一部分它会失败),但是它是有效的。在我的学习经历中,我更关心的是什么是可能的,而不是什么是实际的,所以我很高兴看到至少有两种不同的方法来做我认为应该可以做的事情。即使是坏方法。