Python 我们能否找到从使用';导入的类实例化的对象的"本地"类名;导入为';?

Python 我们能否找到从使用';导入的类实例化的对象的"本地"类名;导入为';?,python,python-import,Python,Python Import,如果我导入一个类并通过子类化将其重命名,那么找到新的类名就相当简单: >>> from timeit import Timer >>> class Test(Timer): ... pass ... >>> test = Test() >>> test.__class__.__name__ 'Test' 但是,如果在导入类时对其进行别名,则该类将保留其主机模块中的名称: >>> from tim

如果我导入一个类并通过子类化将其重命名,那么找到新的类名就相当简单:

>>> from timeit import Timer
>>> class Test(Timer):
...     pass
... 
>>> test = Test()
>>> test.__class__.__name__
'Test'
但是,如果在导入类时对其进行别名,则该类将保留其主机模块中的名称:

>>> from timeit import Timer as Test2
>>> test2 = Test2()
>>> test2.__class__.__name__
'Timer'
稍后,我想提供面向用户的输出,该输出知道他们在名称空间中为类指定的名称。考虑:

def report_stats(timer):
    print("Runtime statistics for %s:" % timer.__class__.__name__)
    ...

有没有一种方法可以得到一个读取“Test2”的字符串,除了在名称空间中迭代变量以测试精确匹配之外?

对于我自己的问题,有一个非常糟糕的答案;我不会接受这个,因为它可能非常脆弱(我只测试了有限的一组调用情况)。我基本上只是为了挑战才找到这个;对于我的实际用例,我很可能会使用更耐用的东西

这假设我们可以访问我们试图作为blah导入的类的init函数,以及某种持久性外部数据存储,至少对于更复杂的边缘情况:

import inspect, dis

class Idiom(object):
    description = None
    alias = None

    def __init__(self, desc):
        global data_ob
        self.description = desc

        if self.__class__.__name__ == 'Idiom':
            #cheat like hell to figure out who called us
            self.alias = data_ob.name_idiom(inspect.currentframe().f_back)
        else:
            self.alias = self.__class__.__name__

class DataOb(object):
    code = None
    locations = {}
    LOAD_NAME = 101
    codelen = None

    def name_idiom(self, frame):
        if not self.code:
            self.code = frame.f_code
            self.codelen = len(self.code.co_code)
            self.locations = {y:x for x, y in dis.findlinestarts(self.code)}

        target_line = frame.f_lineno
        addr_index = self.locations[target_line]+1
        name_index = self.code.co_code[addr_index]

        # there's a chance we'll get called again this line,
        # so we want to seek to the next LOAD_NAME instance(101)
        addr_index += 1
        while addr_index < self.codelen:
            if self.code.co_code[addr_index] == self.LOAD_NAME:
                self.locations[target_line] = addr_index
                break
            addr_index += 1

        return self.code.co_names[name_index]

不,你必须查一下,它可能总是有多个名字。它在定义时的名称是保存在类中的所有名称。当你对它进行子类化时,你不是在重命名它,而是在创建一个以原始类为基础的新类。如果你回答这个问题,@agf,我会接受它。根据我在兔子洞底部发现的可怕的东西,我还将提供我自己的答案。祝贺你,你赢得了本周的邪恶蟒蛇奖。@IgnacioVazquez Abrams我希望我希望它会带来高昂的永久性维护成本。
>>> from rabbit_hole import Idiom as timer_bob
>>> with timer_bob("down the rabbit hole"):
...     waste_some_time = list(range(50000))
... 
timer_bob: down the rabbit hole
    runtime: 0:00:00.001909, children: 0:00:00, overhead: 0:00:00.001909