Функции, методы и сколько аргументов я должен им дать? - PullRequest
0 голосов
/ 15 ноября 2018

Почему следующие строки дают мне тот же результат?

str.upper('hello')

и

'hello'.upper()

Я пытался сделать то же самое с list.append, но получил TypeError.

list.append([1]) 

Не перегружен ли тип str в python? Как этого достичь, написав класс / функцию? Буду признателен за пример.

Спасибо

RP.

Ответы [ 4 ]

0 голосов
/ 15 ноября 2018

С str не происходит ничего волшебного (за исключением того, что у нас есть хороший синтаксический ярлык для создания с использованием ""). Вы можете написать класс, который ведет себя как str и list, чтобы более четко видеть, что здесь происходит.

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') в качестве первого аргумента вызов функции.

0 голосов
/ 15 ноября 2018

Цитата Дейв Кирби s ответ от Отношения между строковым модулем и str :

Существует некоторое совпадение между строковым модулем и типом str, в основном по историческим причинам. В ранних версиях Python str объекты не было методов, поэтому все операции со строками выполнялись функции из строкового модуля. Когда методы были добавлены в ул типа (в Python 1.5?) функции были оставлены в строковом модуле для совместимость, но теперь просто переходим к эквивалентному методу str.

Однако строковый модуль также содержит константы и функции, которые не являются методами на str, такими как форматирование, перевод символов и т. д.

0 голосов
/ 15 ноября 2018

str.upper и list.append обе функции.

str.upper принимает один аргумент.

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

list.append принимает два аргумента.

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

str.upper и list.append (как и другие функции) также являются не дескрипторами данных с методом __get__, который в этом контексте имеет два значения:

  1. Когда вы обращаетесь к функции через класс через точечную запись (str.upper, list.append), вызывается метод __get__ функции (то есть string.upper.__get__ и list.append.__get__), но он возвращает только саму функцию.
  2. Когда вы получаете доступ к функции через экземпляр (my_string.upper, my_list.append), вызывается метод __get__ функции, и он возвращает новый вызываемый , действующий как исходная функция, но с тем, что было «перед точкой», автоматически передается в качестве первого аргумента. .

Вот почему вам нужно передавать аргументы 1 - 1 = 0 при вызове my_string.upper() и аргумент 2 - 1 = 1 при вызове my_list.append(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'
0 голосов
/ 15 ноября 2018

list.append принимает два аргумента - список для изменения и элемент для добавления.Так что вам нужно сделать это так:

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

, что эквивалентно гораздо более популярному:

ls.append(2)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...