类主体中类的Python名称

问题描述 投票:0回答:6

是否可以在类定义主体中获取类名?

例如,

class Foo():
    x = magic() # x should now be 'Foo'

我知道我可以使用类方法在类主体之外静态地执行此操作:

class Bar():
    @classmethod
    def magic(cls):
        print cls.__name__

Bar.magic()

但这不是我想要的,我想要类主体中的类名

python metaprogramming python-2.x
6个回答
8
投票

好的 - 又多了一个解决方案 - 这个实际上并没有那么复杂!

import traceback

def magic():
   return traceback.extract_stack()[-2][2]

class Something(object):
   print magic()

它将打印出“Something”。我不确定提取的堆栈格式是否以任何方式标准化,但它适用于 python 2.6(以及 2.7 和 3.1)


4
投票

AFAIK,类对象在类定义被“执行”之前才可用,因此在类定义期间不可能获取它。

如果您需要类名称供以后使用,但在类定义期间不使用它(例如计算其他字段名称或类似的东西),那么您仍然可以使用类装饰器来自动化该过程。

def classname ( field ):
    def decorator ( klass ):
        setattr(klass, field, klass.__name__)
        return klass
    return decorator

(警告:未经测试。)

通过这个定义,你可以得到类似的东西:

@classname(field='x')
class Foo:
    pass

你会得到字段

x
,其中包含类名,如下所示:

print Foo.x

2
投票

这里有一个针对您的具体情况的可行解决方案,但要注意(我写它主要是为了证明确实可以做这样的事情):

  • 你不应该使用它
  • 非常具体
  • 它有很多限制
  • 我只是在玩这个
  • 这是黑魔法
  • 它可能不适用于您的用例
  • 它不是线程安全的
  • 我已经说过你不应该使用它了吗?

无论如何,这里有代码:

import inspect

def NameAwareClassType():
    frameInfo = inspect.getouterframes(inspect.currentframe())[1]
    codeContext = frameInfo[4][0]
    className = codeContext.split(' ', 1)[1].split('(', 1)[0]

    class ClassNameGlobalRemoverType(type):
        def __new__(mcs, name, bases, dict):
            if name == className:
                del globals()['__clsname__']
            return type.__new__(mcs, name, bases, dict)

    class NameAwareClass(object):
        __metaclass__ = ClassNameGlobalRemoverType

    globals()['__clsname__'] = className

    return NameAwareClass

class A(NameAwareClassType()):

    print __clsname__

    def __init__(self):
        pass

print __clsname__

编辑: https://gist.github.com/1085475 — 您有一个允许在方法执行期间使用

__clsname__
的版本;没有多大意义,因为
self.__class__.__name__
是一种更好的方法,并且
__clsname__
变量不再保存字符串(我正在尝试这个)


1
投票

我不知道在 Python 2.x 中执行此操作的优雅方法 - 但它是一种解释性语言,这意味着以下几行相对简单的东西将执行您想要的操作,并且如果您确定的话,那么这将是安全的正在执行的代码:

classdef = """\
class %(classname)s(object):
    x = '%(classname)s'
    print x
"""
exec classdef % {'classname': 'Foo'}

foo = Foo()
print foo

0
投票

现在可能是一个问题

__qualname__

class AClass:

    def __init__(self):
        print(f"Initializing an object of class {AClass.__qualname__}")

    def __repr__(self):
        return f"{AClass.__qualname__}()"

有了这个定义:

>>> ac = AClass()
Initializing an object of class 'AClass'
>>> ac
Body of AClass.fun

__qualname__
也可以应用于方法。如果在类的主体中定义了方法(或内部类),则可以获得其完全限定名称,例如

# ...
def fun(self):
    print(f"Body of {AClass.fun.__qualname__}")

然后,实例化对象后:

ac = AClass()

ac.fun()
给出:
Body of AClass.fun


-2
投票
class Bar():

    @classmethod
    def magic(cls):
        return cls.__name__

    @property
    def x(self):
        return self.magic()

    def y(self):
        return self.x

>>> a = Bar()
>>> a.x
'Bar'
>>> a.y()
'Bar'

这样您就可以使用

x
作为属性,至少在任何实例和静态方法中。在类方法中,您无论如何都可以从
cls
属性获取类名。

© www.soinside.com 2019 - 2024. All rights reserved.