Хммм ... Я бы почти поклялся, что это сработало для оригинальной оболочки Bourne, но сейчас у меня нет доступа к текущей копии.
Существует, однако, очень тривиальный обходной путь к проблеме.
Измените первую строку сценария:
#!/bin/bash
на
#!/bin/ksh
Et voila! Чтение в конце конвейера работает отлично, если у вас установлена оболочка Korn.
Новое поведение магии super()
было добавлено во избежание нарушения D.R.Y. (Не повторяйте себя), см. PEP 3135 . Чтобы явно указать класс, ссылаясь на него как на глобальный, также подвержены тем же проблемам перезаписи, которые вы обнаружили с помощью самого super()
:
class Foo(Bar):
def baz(self):
return super(Foo, self).baz() + 42
Spam = Foo
Foo = something_else()
Spam().baz() # liable to blow up
То же самое относится к использованию декораторов классов, где декоратор возвращает новый объект, который перепроверяет имя класса:
@class_decorator_returning_new_class
class Foo(Bar):
def baz(self):
# Now `Foo` is a *different class*
return super(Foo, self).baz() + 42
Магическая ячейка super()
__class__
уклоняется от этих проблем, предоставляя вам доступ к исходному объекту класса.
PEP был выпущен Guido, который изначально предполагал super
стать ключевым словом , а идея использования ячейки для поиска текущего класса была также его . Конечно, идея сделать это ключевым словом была частью первого черновика PEP .
Однако на самом деле сам Гвидо, который затем отступил от ключевое слово как «слишком магическое» , предлагая вместо этого текущую реализацию. Он предположил, что использование другого имени для super()
может быть проблемой :
В моем патче используется промежуточное решение: предполагается, что вам нужно
blockquote>__class__
всякий раз, когда вы используете переменную с именем'super'
. Таким образом, если вы (глобально) переименуетеsuper
вsupper
и используетеsupper
, но неsuper
, он не будет работать без аргументов (но он все равно будет работать, если вы передадите его либо__class__
, либо фактическое объект класса); если у вас есть несвязанная переменная с именемsuper
, все будет работать, но метод будет использовать несколько более медленный путь вызова, используемый для переменных ячейки.Итак, в конце концов, это был сам Гвидо что с использованием ключевого слова
super
не было правильно, и что предоставление магии__class__
ячейки было приемлемым компромиссом.Я согласен с тем, что магическое, неявное поведение реализации несколько удивительно, но
super()
является одной из самых неправильно применяемых функций на языке. Просто взгляните на все неправильныеsuper(type(self), self)
илиsuper(self.__class__, self)
вызовы, найденные в Интернете; если какой-либо из этого кода когда-либо вызывался из производного класса , у вас было бы исключение с бесконечной рекурсией . По меньшей мере упрощенный вызовsuper()
без аргументов позволяет избежать проблемы .Что касается переименованного
super_
; просто ссылку__class__
в свой метод , а также , и он снова будет работать. Ячейка создается, если вы ссылаетесь на именаsuper
или__class__
в вашем методе:>>> super_ = super >>> class A(object): ... def x(self): ... print("No flipping") ... >>> class B(A): ... def x(self): ... __class__ # just referencing it is enough ... super_().x() ... >>> B().x() No flipping
def super(of_class=magic __class__)
типаself.super(); def super(self): return self.__class__
? – Charles Merriam 14 March 2014 в 18:28super()
без аргументов; он в основном имеет дело с why i>, он существует.super()
, в методе класса, эквивалентенsuper(ReferenceToClassMethodIsBeingDefinedIn, self)
, гдеReferenceToClassMethodIsBeingDefinedIn
определяется во время компиляции, прикрепляется к методу как закрытие с именем__class__
, аsuper()
будет искать как из вызывающего кадра во время выполнения. Но на самом деле вам не нужно все это знать. – Martijn Pieters♦ 14 March 2014 в 18:37super()
нигде не близок к автоматически созданной функции i>, no. – Martijn Pieters♦ 14 March 2014 в 18:38__class__
в вашем методе i>. Вы использовали имяsuper
в своей функции. Компилятор видит это и добавляет закрытие__class__
. – Martijn Pieters♦ 10 February 2018 в 19:27type(self)
дает тип current , который не совпадает с типом, на котором определен метод. Таким образом, классFoo
с методомbaz
нуждается вsuper(Foo, self).baz()
, потому что он может быть подклассифицирован какclass Ham(Foo):
, и в этот моментtype(self)
естьHam
, аsuper(type(self), self).baz()
даст вам бесконечный цикл. См. Сообщение, на которое я ссылаюсь в своем ответе: При вызове super () в производном классе я могу передать сам .__ class __? – Martijn Pieters♦ 23 February 2018 в 18:37