所以我有这个问题,我希望以这种方式得到一个python类的名称:
class TestClass():
myName = (get class name here automatically)
saveDirectory = os.path.join(saveDir, myName) # so i can save it in unique location
def __init__(self):
pass # do something
但是,在__class__.__name__
创建时,似乎myName
实际上并不存在。所以我被迫把它放到__init__()
函数中,就像这样:
class TestClass():
def __init__(self):
self.myName = self.__class__.__name__
saveDirectory = os.path.join(saveDir, self.myName) # so i can save it in unique location
pass # do something
但这有一个很大的问题,因为在我实例化类之前我无法获取类的名称,我想为每个要保存在saveDirectory中的类的实例创建几千兆字节的数据,所以它可以以后再重复使用。所以我实际上并不想继续使用我目前的解决方案。
有没有得到我想要的课程名称?或者我只是在做梦?
编辑:
谢谢你们提出的好建议。我将花一点时间看一下Metaclasses。否则,我可能会全局创建一个字典,而是引用这些实例化的类。
答案 0 :(得分:7)
只需使用方法吗?
class TestClass(object):
@classmethod
def get_save_directory(cls):
return os.path.join(save_dir, cls.__name__)
或者你可以只有一个指示保存目录的class属性;少魔法通常是件好事。另外,您可以在不破坏存储空间的情况下更改班级名称。
还有什么?千兆字节?!
答案 1 :(得分:5)
在课程定义中实际执行您尝试的操作的唯一方法是使用metaclass:
def saveDirMeta(name, bases, dct):
dct['saveDirectory'] = os.path.join(saveDir, name)
return type(name, bases, dct)
class TestClass(object):
__metaclass__ = saveDirMeta # this adds the 'saveDirectory' attribute
def __init__(self):
pass # do something
或者在Python 3.x上:
class TestClass(metaclass=saveDirMeta):
def __init__(self):
pass # do something
这绝不仅仅是使用以下内容:
class TestClass():
saveDirectory = os.path.join(saveDir, 'TestClass')
def __init__(self):
pass # do something
答案 2 :(得分:2)
我猜你正在做的事情是不可能的,因为当你这样做时,这个课程甚至不存在:
myName = (get class name here automatically)
但是在解释了类之后不久,您可以将类对象传递给其他函数 为你做这份工作。
In [1]: def save_class(cl):
myName = cl.__name__
print myName #or do whatever you wanna do here
...:
In [2]: class A:pass
In [3]: save_class(A)
A
答案 3 :(得分:2)
在课堂解释过程中,还没有“那里”。所以,是的,您的初始示例显示的是不可能的。但是,请解释为什么在课堂上技术上存在之前需要知道这一点?
如果对这个悬而未决的问题给出一个很好的答案,那就是试图从这个名字中获取该名称:
1. outside the interpreted class definition, uninstantiated
class demo(object):
pass
print demo.__name__ # 'demo'
2. from within the class definition, uninstantiated (or instantiated ;-)
class demo2(object):
@classmethod
def myName(cls):
return cls.__name__
print demo2.myName() # 'demo2'
print demo2().myName() # 'demo2'
or
3. within an actual instance of the class
class demo3(object):
def myClassName(self):
return self.__class__.__name__
print demo3().myClassName() # 'demo3'
除此之外,请编辑问题并添加一些细节,解释为什么您的初始尝试需要按照您想要的方式工作,在实例化之前,但在内部定义,而您的第二个示例是有问题的。另外,saveDir如何通过/来自? (班级以外的全球?)请显示一些代码,说明您打算如何使用您想要的工作。可能有一种方法可以重新设计从这里到达那里,实际上如果不是字面上的话。
答案 4 :(得分:2)
除了F J answer中的元类,我可以想到两个其他方式。我会从看起来更漂亮的开始。您不需要使用元类;有时候描述符就足够了。
class ClassNameDescriptor(object):
def __get__(self, instance, owner):
return owner.__name__
class BaseClass(object):
name = ClassNameDescriptor()
class Foo(BaseClass):
pass
另一方面,如果你真的需要在里面类体(不太可能)的类名,你可以窥探调用堆栈。它出现在源代码中的类名是由类定义执行的代码对象:
import sys
def get_class_name_from_inside_class():
return sys._getframe().f_back.f_code.co_name
class Foo(object):
name = get_class_name_from_inside_class()
print name
在目前为止提供的内容中,只有 这最后一个让你在类体内部使用名称作为字符串,不幸的是,这在所有版本的python中都不起作用特别是IronPython没有实现调用堆栈内省,因为它在DLR中不可用。
有一种方法可以在没有内省堆栈的情况下获得它。它类似于F J使用元类提供的答案,而是使用Python 3中提供的__prepare__
功能:
class namedMeta(type):
def __prepare__(mcls, name, bases, **kwargs):
return {'name': name}
class Foo(metaclass=named):
print name
答案 5 :(得分:0)
试试这个。你可以通过_class
来引用你当前的课程。 (我使用的是python 2.7)
class Meta(type):
def __init__(self, *args):
super(Meta, self).__init__(*args)
self._class = self
self.saveDir = str(self._class)
class Wow(object):
__metaclass__ = Meta
>>> Wow.saveDir
>>> Wow().saveDir
答案 6 :(得分:0)
从python 3.3开始,您可以使用__qualname__
变量:
class TestClass():
myName = __qualname__