我对C,C ++,C#和Objective-C非常流利,但对Python来说却相当新。而我正在尝试使用Python + Django。我遇到的第一件事是,如果使用python 2.x,Django模型的“to string”功能是通过__unicode__
完成的,而对于3.x,它是通过__str__
完成的。< / p>
我想在我的类中只定义一次“to string”方法:相同的主体,根据python版本的不同签名。
例如,在C和C ++中,这可以通过预处理器宏完成(在编译时,但它可以达到目的)。在C#中,通过内省,在Objective-C中也是如此(通过运行时函数)。但是我不确定将它拉出来的“优雅”方式是在Python中。到目前为止我试过这个:class A(models.Model):
def _infoMethod(self):
# blah..
class B(models.Model):
def _infoMethod(self):
# blah..
# ...
class N(models.Model):
def _infoMethod(self):
# blah..
for c in inspect.getmembers(sys.modules[__name__], inspect.isclass):
if callable(getattr(c[1], "_infoMethod", None)):
setattr(c[1], '__unicode__' if sys.version_info.major < 3 else '__str__', c[1]._infoMethod)
它确实有效,但是在解析所有类之后我需要迭代模块中的类,找到哪些具有该方法并为每个类动态设置“别名”,这似乎有些麻烦。我想知道是否有一种更“元”的方式。涉及在类等内部替换方法签名中的标识符部分的内容等
答案 0 :(得分:3)
最简单的方法就是
class Foo(models.Model):
def __unicode__(self):
...
__str__ = __unicode__
答案 1 :(得分:2)
您可以使用类装饰器:
def deco(cls):
setattr(cls, '__unicode__' if sys.version_info.major < 3 else '__str__', cls._infoMethod)
return cls
@deco
class B(models.Model):
def _infoMethod(self):
#blah
但是,您也可以使用__str__ = __unicode__
定义类,而不是花哨。
答案 2 :(得分:1)
我可能不会完全关注你,但你不能得到你想要的东西吗?
class N(models.Model):
def _infoMethod(self):
__str__ = _infoMethod
__unicode__ = _infoMethod
Python 3.x有__str__
,Python 2.x有__unicode__
,它们都映射到相同的底层函数。
答案 3 :(得分:1)
easy 方法是通过为所有模型使用基类...
class ModelBase(models.Model):
if python3:
def __str__(self):
return self._infoMethod()
else:
def __unicode__(self):
return self._infoMethod()
现在只是在任何地方的子类......
class A(ModelBase):
def _infoMethod(self):
return 'foo'
...
当然,如果您定义了太多方法,通常不在乎......您可以只有__str__
和__unicode__
两个而不用担心Django想要打电话,因为他们都在场:
class ModelBase(models.Model):
def __str__(self):
return self._infoMethod()
def __unicode__(self):
return self._infoMethod()
此处的另一个优点是,您不需要在所有模型子类中对__str__
和__unicode__
进行别名,因为其他一些答案需要 - 只需执行一次即可#39;重新完成。
最后,如果你不想保持_infoMethod
活着,你可以这样做:
class ModelBase(models.Model):
def __unicode__(self):
# I choose `unicode` here since it is a superset of __str__ ...
return self.__str__()
class A(ModelBase):
def __str__(self):
return 'Hello World!'