我有一个带有getter和setter方法的模型类,以及偶尔的静态方法。我想强制使用unicode字符串作为特定方法的参数,并且使用装饰器是我的第一个想法。现在我有这样的事情:
import types
class require_unicode(object):
def __init__(self, function):
self.f = function
def __call__(self, string):
if not isinstance(string, types.UnicodeType):
raise ValueError('String is not unicode')
return self.f(string)
class Foo(object):
something = 'bar'
@staticmethod
@require_unicode
def do_another(self, string):
return ' '.join(['baz', string])
@require_unicode
def set_something(self, string):
self.something = string
foo = Foo()
foo.set_something('ValueError is raised')
foo.set_something(u'argument count error')
foo.do_another('ValueError is raised')
foo.do_another(u'argument count error')
在上面的代码中,decorator __call__
内部的方法调用因错误的参数计数而失败(因为'foo'对象引用丢失了?)。在做一些愚蠢的事情之前我想问你们。应该怎么做?
答案 0 :(得分:1)
我认为,问题出在@staticmethod装饰器上,而不是你的require_unicode装饰器。与classmethods不同,Staticmethods不接受对类的引用作为第一个参数,因此您的参数签名是错误的。
您必须将do_another更改为@classmethod,或从参数中删除self
。
编辑:并且,请注意, - @ classmethod-decorated方法接收类作为第一个参数,而实例方法接收对类实例的引用 (自)。因此,最好将第一个参数命名为classmethod“cls”或其他东西,而不是“self”,这样就不会让任何人感到困惑。
答案 1 :(得分:0)
我认为这是unpythonic - 你永远不应该检查你的参数的类型,而是检查它们是否具有必要的方法和属性。最简单的方法是假设它们在那里然后获得异常,但我想你也可以做getattr
。只是不检查事物的类型。
答案 2 :(得分:0)
另一种选择是使用断言。这取决于是否将非unicode类型传递给您的方法应该被视为编程错误,这在开发过程中应该是明显的。
import types
class Foo:
def set_something(self, string):
assert isinstance(string, types.UnicodeType), 'String is not unicode'
self.something = string
只要AssertionError
不是unicode类型,这将引发string
异常,但仅当Python解释器以“deubg”模式运行时才会引发-O
异常。如果使用{{1}}选项运行Python,则解释器会有效地忽略断言。