【问题标题】:Functions, methods, and how many arguments do I have to give them?函数、方法以及我必须给它们多少个参数?
【发布时间】:2019-04-18 16:18:12
【问题描述】:

为什么下面几行给了我同样的结果?

str.upper('hello')

'hello'.upper()

我尝试对list.append 做同样的事情,但得到了TypeError

list.append([1]) 

Python 中的str 类型是否重载?如何通过编写类/函数来实现?我会很感激一个例子。

【问题讨论】:

  • 您希望在哪个列表中添加 1?
  • 你的list.append([1]) 会在哪里附加?
  • 您的第一个大写示例与将整数附加到列表之间有什么关系?
  • “如何通过编写类/函数来实现?” 怎样才能实现?完全不清楚您要的是什么。
  • 这个问题只是表面上的琐碎。 +1

标签: python string list function methods


【解决方案1】:

list.append 接受两个参数 - 要修改的列表和要附加的元素。所以你需要这样做:

ls = [1]
list.append(ls, 2)

这相当于更流行的:

ls.append(2)

【讨论】:

    【解决方案2】:

    str.upperlist.append 都是函数。

    str.upper 接受一个参数。

    >>> str.upper('test')
    'TEST'
    

    list.append 接受两个参数。

    >>> my_list = []
    >>> list.append(my_list, 1)
    >>> my_list
    [1]
    

    str.upperlist.append(与其他函数一样)也是带有 __get__ 方法的 non-data-descriptors,在这种情况下有两个含义:

    1. 当您通过点符号(str.upperlist.append)通过类访问函数时,会调用函数的__get__ 方法(即string.upper.__get__list.append.__get__),但它只返回函数本身。
    2. 当您通过实例my_string.uppermy_list.append)访问函数时,函数的__get__ 方法被调用,它会返回一个新的可调用对象像原始函数一样,但是“在点前面”的任何内容都自动作为第一个参数传递。 .

    这就是为什么在调用 my_string.upper() 时需要传递 1 - 1 = 0 参数和在调用 my_list.append(1) 时需要传递 2 - 1 = 1 参数的原因。

    >>> 'my_string'.upper()
    'MY_STRING'
    >>>
    >>> my_list = []
    >>> my_list.append(1)
    >>> my_list
    [1]
    

    甚至可以通过显式调用 __get__ 并将要绑定的参数(点之前的内容)作为其参数来获取这些修改后的可调用对象(方法)。

    >>> my_string = 'my_string'
    >>> upper_maker = str.upper.__get__(my_string)
    >>> upper_maker()
    'MY_STRING'
    >>> 
    >>> my_list = []
    >>> appender = list.append.__get__(my_list)
    >>> appender(1)
    >>> my_list
    [1]
    

    最后,这是一个简短的示例,演示描述符实例如何检测它们是通过其所有者类还是通过实例进行访问的。

    class Descriptor:
        def __get__(self, instance, owner_class):
            if instance is None:
                print('accessed through class')
                # list.append.__get__ would return list.append here
            else:
                print('accessed through instance')
                # list.append.__get__ would build a new callable here
                # that takes one argument x and that internally calls
                # list.append(instance, x)
    
    class Class:
        attribute = Descriptor()
    
    Class.attribute # prints 'accessed through class'
    
    instance = Class()
    instance.attribute # prints 'accessed through instance'
    

    【讨论】:

    • str.upperlist.append 不属于 strlist 类下的实例方法类别吗?
    • @Idlehands 这有点字斟句酌。如果我必须尝试非常正确,我会说:str.upperlist.append 是在使用非 None instance 参数调用它们的 __get__ 方法时返回方法的函数 - 我将在其中定义作为可调用的方法,它部分(即带有绑定的第一个参数)应用在类中定义的函数。
    • 感谢您的澄清,我真的很困惑,因为我的背景不是 comp-sci,所以术语和范式对我来说是弱点。我的理解是,在类中定义的任何函数(即其名称前的点)始终是一种方法(实例/类/静态),因此是我最初的问题。在这种情况下,我认为str.upper 的定义与class str: def upper(self): 类似,它可以以instance.upper()str.upper(instance) 运行。
    • @Idlehand 整个描述符主题很难。编写代码时的经验法则:my_class.function_name 为您提供了一个必须向其传递所有参数的函数。 instance_of_class.function_name 为您提供了一个方法,instance_of_class 作为第一个参数自动传递给该方法(通常命名为 self)。
    【解决方案3】:

    引用Dave Kirbys 来自Relationship between string module and str 的回答:

    string模块和str类型有一些重叠, 主要是历史原因。在 Python str 对象的早期版本中 没有方法,所以所有的字符串操作都是用 来自字符串模块的函数。当方法被添加到 str 类型(在 Python 1.5 中?)函数留在字符串模块中 兼容性,但现在只转发到等效的 str 方法。

    然而字符串模块也包含常量和函数 不是 str 上的方法,例如格式化、字符翻译等。

    【讨论】:

    • 这可能是可以在这里给出的最佳答案。不明白-1。干得好。
    • 它可能被否决了,因为它实际上是相关线程中另一个答案的直接引用。
    【解决方案4】:

    str 并没有什么神奇之处(除了我们有一个很好的语法快捷方式来创建一个使用“”)。您可以编写一个行为类似于 strlist 的类,以更清楚地看到这里发生了什么。

    class MyClass():
        def __init__(self, arg):
            self.val=str(arg)
    
        def do_thing(self):
            self.val = "asdf"
    
        def do_thing_with_arg(self, arg):
            self.val = "asdf " + str(arg)
    
        def __repr__(self):
            return self.val
    
    
    my_thing = MyClass("qwerty")
    
    # this is like 'hello'.upper()
    my_thing.do_thing()
    print(my_thing)
    # it prints 'asdf'
    
    my_thing = MyClass("qwerty")
    
    # this is like str.upper('hello')
    MyClass.do_thing(my_thing)
    print(my_thing)
    # it prints 'asdf'
    
    my_thing = MyClass("qwerty")
    
    # this is like my_list.append('qwerty')
    my_thing.do_thing_with_arg('zxcv')
    print(my_thing)
    # it prints 'asdf zxcv'
    
    my_thing = MyClass("qwerty")
    
    # this is like list.append(my_list, 'qwerty')
    MyClass.do_thing_with_arg(my_thing, 'zxcv')
    print(my_thing)
    # it prints 'asdf zxcv'
    

    简短的版本是,您正在调用看起来像类的“实例方法”,但您自己提供实例 ('self') 作为第一个参数函数调用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-23
      • 2017-03-03
      相关资源
      最近更新 更多