代码之家  ›  专栏  ›  技术社区  ›  Prof. Falken

在Python中处理不同类型的规范方法是什么?

  •  6
  • Prof. Falken  · 技术社区  · 14 年前

    我有一个函数,在那里我需要为我调用的另一个程序生成不同的输出字符串,这取决于它想要的类型。

    基本上,被调用的程序需要一个命令行参数来告诉它用哪种类型来调用。

    很高兴我找到了 this answer 关于如何检查变量的类型。但我注意到人们也提出了反对意见,即检查类型会暴露出“不面向对象”的设计。那么,是否有其他的方法,可以假定的更“面向对象”的方法来处理这个问题而不显式地检查类型?

    我现在得到的代码是这样的:

    def myfunc(val):
        cmd_type = 'i'
        if instance(val, str):
            cmd_type = 's'
    
        cmdline = 'magicprogram ' + cmd_type + ' ' + val
        Popen(cmdline, ... blah blah)
        ...
    

    这很好,但我只是想知道是否有一些技术我不知道。

    4 回复  |  直到 11 年前
        1
  •  3
  •   martineau    14 年前

    我不认为 双重调度 多种方法 这与人们对另一个人的回答所持的反对意见特别相关,也没有多大关系。

    毫不奇怪,为了使您正在做的事情更面向对象,您需要向其中引入一些对象(以及相应的类)。将每个值设为类的实例将允许(实际上,实际上是强制)停止检查其类型。下面对示例代码的修改显示了一种非常简单的方法:

    class Value(object):
        """ Generic container of values. """
        def __init__(self, type_, val):
            self.type = type_   # using 'type_' to avoid hiding built-in
            self.val = val
    
    def myfunc(val):
        # Look ma, no type-checking!
        cmdline = 'magicprogram {obj.type} {obj.val}'.format(obj=val)
        print 'Popen({!r}, ... blah blah)'.format(cmdline)
        # ...
    
    val1 = Value('i', 42)
    val2 = Value('s', 'foobar')
    
    myfunc(val1)  # Popen('magicprogram i 42', ... blah blah)
    myfunc(val2)  # Popen('magicprogram s foobar', ... blah blah)
    

    如果在 Value 类来间接访问它的属性,但只要执行上面的操作,就可以摆脱臭名昭著的类型检查。一个更面向对象的设计可能对每种类型都有不同的子类。 价值 它们都为客户机共享一组通用的方法,比如 myfunc() ,用于创建、操作和从中提取信息。

    使用对象的另一个好处是不需要修改 myfunc()。 如果/当您向应用程序添加对新类型“值”的支持时——如果您对“值”本质的抽象是一个好的抽象,那就是。

        2
  •  5
  •   pillmuncher    14 年前
        3
  •  3
  •   Prof. Falken    13 年前
        But I noticed how people also raised objections, 
    that checking for types betrays a "not object oriented" design
    

    实际上,它被称为 Duck typing style (“如果它看起来像鸭子,嘎嘎叫得像鸭子,那么它一定是鸭子。”)而且是Python语言推荐使用这种编程风格。

    用鸭子打字,打个电话来 EAFP (请求宽恕比允许更容易)

        presumable more "more object oriented" way of handling this without 
       explicitly checking for type?
    

    你的意思是更多的蟒蛇,基本上,在你的情况下,更多的蟒蛇是这样的:

    def myfunc(val):
        cmd_type = 'i'
    
        # forget about passing type to your magicprogram
        cmdline = 'magicprogram  %s ' % val 
        Popen(cmdline, ... blah blah)
    

    在你的魔术师节目中(我不知道是你的剧本还是…),因为 在任何情况下,您的程序都会得到一个字符串,所以只需尝试将其转换为 脚本接受;

    from optparse import OptionParser
    
    # ....
    
    if __name__ == '__main__':
    
        parser = OptionParser(usage="blah blah")
    
        # ...
        (options, args) = parser.parse_args()
    
        # Here you apply the EAFP with all type accepted.
        try:
            # call the function that will deal with if arg is string
            # remember duck typing.
        except ... :
            # You can continue here
    

    我不知道你所有的代码是什么,但是你可以按照上面的例子,它更像是蟒蛇,记住每个规则都有例外,所以你的情况可能是例外。 你最好检查一下类型。

    希望这能帮你解决问题。

        4
  •  1
  •   stonemetal    14 年前

    与如何设计一个小函数相比,这更像是一个大问题中的工程。有许多不同的方法来实现它,但它们或多或少地分解为相同的一般思想过程。在已知val类型的后面,它应该指定如何将其转换为命令行arg。如果是我,我可能会让val成为一个类,它有一个to命令行函数,可以做正确的事情。还可以将特定于类型的myfunc函数赋给变量,然后在需要时调用该函数。

    编辑:解释最后一个版本

    Val = "a string"
    myfunc = myfuncStringVersion
    

    或多或少地,在类中包装val所做的相同的事情只是分解成一个值和函数,因为您可能不想在类中包装val。