【问题标题】:How to enforce unicode arguments for methods?如何为方法强制执行 unicode 参数?
【发布时间】:2010-12-13 02:34:53
【问题描述】:

我有一个带有 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')

在上面的代码中,装饰器的__call__ 内部的方法调用由于参数计数错误而失败(因为缺少'foo' 对象引用?)。在做一些愚蠢的事情之前,我想问你们。这应该怎么做?

【问题讨论】:

    标签: python unicode arguments decorator


    【解决方案1】:

    另一种选择是使用断言。这取决于将非 unicode 类型传递到您的方法中是否应该被视为在开发过程中应该很明显的编程错误。

    import types
    class Foo:
        def set_something(self, string):
            assert isinstance(string, types.UnicodeType), 'String is not unicode'
            self.something = string
    

    每当string 不是 unicode 类型时,这将引发AssertionError 异常,但仅当 Python 解释器以“deubg”模式运行时。如果您使用 -O 选项运行 Python,则解释器会有效地忽略断言。

    【讨论】:

    • 当然,我也想过这个,但认为装饰器会更干净。
    • 那么你觉得哪个更干净? IMO assert 更加明显,因为检查就在方法的开头,而不是隐藏在可能从其他地方导入的类中。在使用-O 运行 python 时,您还可以获得断言有效地成为 NOP 的性能优势。
    【解决方案2】:

    我认为这是不符合 Python 标准的——你永远不应该检查参数的类型,而是检查它们是否具有必要的方法和属性。最简单的方法是假设它们在那里并获得异常,但我想你也可以这样做getattr。只是不要检查事物的类型。

    【讨论】:

    • 我知道它是非 Python 的,但是在这里防止编码字符串可以让我在以后将给定数据保存到数据库时免于很多麻烦。
    • @eclair:一旦你绝对肯定需要 unicode,只要调用unicode() 就你所拥有的并称之为好。
    【解决方案3】:

    我认为,您的问题在于 @staticmethod 装饰器,而不是您的 require_unicode 装饰器。与类方法不同,静态方法不接收对类的引用作为第一个参数,因此您的参数签名是错误的。

    您必须将 do_another 更改为 @classmethod,或从参数中删除 self

    编辑:并且,请注意,-@classmethod-decorated 方法接收 class 作为第一个参数,而实例方法接收对 类实例的引用 (自己)。因此,最好将类方法的第一个参数命名为“cls”或其他名称,而不是“self”,以免混淆任何人。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-06-08
      • 1970-01-01
      • 2020-05-12
      • 2022-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多