Что делает <type>.<attr> во время совпадения/регистра?

Как правило, код <type>(arg1=value1) заменяется на код <type>(attr1=value1) во время case в операторе сопоставления . Это позволяет делать очень интересные и сложные снимки.

Например, мы можем спросить: «Есть ли у моего экземпляра атрибут под названием «sort», если да, то зафиксируйте его»:

match [1,2,3]:
    case list(sort=f): # this isn't a call, it is an attr-capture statement
        print(f)

Поскольку первым (и единственным) позиционным аргументом экземпляра списка являются значения списка, вы также можете захватывать эти элементы:

match [1,2,3]:
    case list((x,*y),sort=f): # here we are capturing the 'attr' called 'sort' as 'f'
        print(x,y,f)

Аналогичным образом вы можете указать совпадающие значения вместо того, чтобы фиксировать их в переменных:

g = list.sort
match [1,2,3]:
    case list((1,*y),sort=g):  # here we ask if the attr 'sort' is the same as 'g'
        print(y)

Однако теперь меня смущает следующее:

match [1,2,3]:
    case list(x,sort=list.sort):  # fails to match, but why???
        print(x)

Я бы подумал, что это не удастся, потому что list.sort означает нечто иное, чем указание «функции сортировки списка». Возможно, sort=list.sort означает «есть ли у меня атрибут под названием «сортировка», который сам имеет тип «список», который также имеет атрибут под названием «сортировка»». Итак, я попробовал:

match [1,2,3]:
    case list.sort:  # also fails, why?
        print('ya')

Итак, list.sort не означает, что мне нужен список типов с атрибутом сортировки. Итак, я попробовал:

match list.sort:
    case list.sort: # does match, wait, what?
        print('ya')

Это работает. Итак, list.sort во время case означает использование функции sort типа list, но тогда почему list(sort=list.sort) не удалось?


Пример захвата атрибута «y» и сопоставления атрибута «x»:

class P:
    def __init__(self,a,b):
        self.x,self.y = a+b,a-b
match P(5,6):
    case P(x=11,y=a): # a is a new variable, 11 is a match
        print(a)

«здесь мы спрашиваем, совпадает ли атрибут 'sort' с 'g'» - я не думаю, что это правда, все, что g было раньше, затеняется захватом метода sort совпадения.

jonrsharpe 15.05.2024 21:21
list.sort — это функциональный объект. Он никогда не будет соответствовать объекту списка, но, конечно, он может соответствовать самому себе.
Tim Roberts 15.05.2024 21:21

@jonrsharpe, но он не перезаписывает другие значения атрибутов (1,...) в кортеже. вы можете проверить это для пользовательского класса, установив для атрибута значение «7», а затем указав его вместо его захвата.

Bobby Ocean 15.05.2024 21:22

@TimRoberts верно, но тогда почему «список(sort=list.sort)» не удается захватить?

Bobby Ocean 15.05.2024 21:24

Как бы вы переопределили значение 1?! Я не понимаю, почему вы думаете, что sort=f будет захватывать атрибут sort, соответствующий f (правильно, как показывают ваши выходные данные), но решаете, что sort=g делает что-то совершенно другое.

jonrsharpe 15.05.2024 21:25

@jonrsharpe именно так работает документация. указание того, что уже существует, означает «сопоставление», указание новой переменной означает «захват». Я добавлю пример.

Bobby Ocean 15.05.2024 21:26

Но вы можете продемонстрировать, например. g = "not the list.sort method" что после матча снова <built-in method sort ..., хотя [1, 2, 3].sort совсем не та строка. 11 не является существующей переменной, идентификатором; это ценность. list.sort не является идентификатором, поэтому рассматривается как значение.

jonrsharpe 15.05.2024 21:28

@jonrsharpe Боже мой, вы не можете использовать определенные переменные при захвате. Я никогда этого не осознавал. Что это говорит о «списке (сортировка = список. сортировка)»? Что оно делает?

Bobby Ocean 15.05.2024 21:32

@jonrsharpe, вы говорите, что list.sort рассматривается как значение, но, похоже, это не так, поскольку «list(sort=list.sort)» не соответствует экземпляру [1,2,3], хотя его атрибут "sort" на самом деле является "list.sort".

Bobby Ocean 15.05.2024 21:34

«it's attr «sort» на самом деле является «list.sort»» — list.sort — это <method 'sort' of 'list' objects>, а не <built-in method sort of list object at 0x...>. Если вы учли, например. l = [1, 2, 3] и использовали list(sort=l.sort), связанный метод того же экземпляра, вы увидите, что он соответствует этому случаю.

jonrsharpe 15.05.2024 21:36

@jonsharpe я никогда не знал, что методы класса — это не те же методы, что и экземпляры, так всегда было?

Bobby Ocean 15.05.2024 21:43

Пожалуйста, вносите пояснения с помощью правок, а не комментариев, удаляйте и отмечайте устаревшие комментарии. Комментарии не для того, чтобы задавать новые вопросы. Задайте в своем посте 1 (конкретный, не повторяющийся) вопрос. Если вы получаете что-то, чего не ожидаете, когда приводите минимально воспроизводимый пример , скажите, чего вы ожидали и почему это обосновано авторитетной документацией; в противном случае вы просто просите переписать документацию без каких-либо подробностей о том, что вы в ней делаете или чего не понимаете или понимаете неправильно. Как задать вопрос Справочный центр

philipxy 30.06.2024 10:57
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
12
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

list.sort — это дескриптор, поэтому он не будет соответствовать sort=, который будет методом или функцией.

Вы можете видеть, что тип f является встроенным методом:

match [1,2,3]:
    case list(x,*y), sort=f): # inspect the capture of `sort` as `f`
        print('match', f) # match <built-in method sort of list object at 0x104d94c80>

Но тип list.sort не таков:

>>> type(list.sort)
method_descriptor
>>> list.sort is [1,2,3].sort
False

Но если вы используете метод из того же экземпляра списка, это работает:

foo = [1,2,3]
match foo:
    case list((x, *y), sort=foo.sort):
        print('matched')

Но для меня нет особого смысла сопоставлять атрибут sort, поскольку он различен для каждого экземпляра списка:

>>> x = [1,2,3]
>>> y = [1,2,3]
>>> x.sort is y.sort
False
>>> x.sort == y.sort
False

Спасибо! я никогда не осознавал, что [1,2,3].sort is list.sort — ложь. Я всегда думал об экземплярах, вызывающих методы, как о вызовах методов, которые я определил в классе, я никогда не замечал, что Python разделяет их. так было всегда?

Bobby Ocean 15.05.2024 21:45
list.sort — обычная функция. [1,2,3].sort — связанный метод (экземпляр types.MethodType, который обертывает как [1,2,3], так и list.sort).
chepner 15.05.2024 21:46

Другая вещь, которую здесь, вероятно, следует охватить, — это фундаментальное различие между sort=f (идентификатор -> привязывает значение) и sort=list.sort (не идентификатор -> другой уровень шаблона).

jonrsharpe 15.05.2024 21:47

Говоря языком match, f — это шаблон захвата, а list.sort — это шаблон значения.

chepner 15.05.2024 21:47

@chepner да, но, похоже, это не уникально для list, похоже, что в любом class P: pass тогда P.__init__ is P().__init__ неверно.

Bobby Ocean 15.05.2024 21:48

Во второй строке первого фрагмента кода есть несовпадающие круглые скобки.

mkrieger1 15.05.2024 21:48

Вы можете подумать о [1,2,3].sort что-то вроде list.sort.__get__([1,2,3], list).

wim 15.05.2024 21:48

Связанные методы всегда представляли собой разные объекты для каждого экземпляра. Однако функции и статические методы разные. В Python2 несвязанные методы также отличались от функций. В Python3 несвязанные методы — это просто функции. Если бы вы выполнили ту же самую проверку со статическим методом, она фактически работала бы так, как ожидалось, поскольку статические методы класса — это тот же объект, что и статический метод в каждом экземпляре.

sytech 15.05.2024 21:49

Другим элементом является понимание того, что происходит, когда вы используете идентификатор (например, f) в операторе match вместо местоположения/значения (name.name или "literal value"), но я думаю, что другие это уже рассмотрели. Для полноты и авторитетности источника, из PEP 636: «голое имя без точек) всегда будет интерпретироваться как шаблон захвата».

sytech 15.05.2024 21:54

@sytech да, я начинаю это понимать. Сопоставление регистра — это что-то вроде расширенной формы распаковки, например [(x,y),z] = [(1,2),(3,4)] ; так что это имеет смысл. вероятно, именно поэтому в коде есть часть «if», чтобы вы могли записать и затем сравнить, если необходимо.

Bobby Ocean 15.05.2024 22:01

Другие вопросы по теме