Например, Python, похоже, не
есть метаклассы.
Конечно, это так - просто неявно генерирует новый метакласс для каждого класса: он использует тот же метакласс, что и родительский класс, или type
по умолчанию. Философия дизайна Python, также известная как «Дзен Питона», может быть прочитана с помощью import this
по подсказке интерактивного переводчика; здесь применим второй пункт: «Явное лучше, чем неявное».
В Python 2.X вы указываете пользовательский метакласс со следующим синтаксисом:
class sic:
__metaclass__ = mymeta
...
В Python 3.X более элегантно используется синтаксис именованных аргументов:
class sify(metaclass=mymeta):
...
Smalltalk не имеет
Концепция генераторов.
Генераторы Python являются первоклассными (обычно автономными) функциями, а Smalltalk не имеет понятия «автономных» функций - у него есть методы внутри классов. Но у него, конечно, есть итераторы - как классы, конечно:
iterator := aCollection iterator.
[iterator hasNext] whileTrue: [iterator next doSomething].
Поскольку Smalltalk имеет первоклассные «блоки кода» (Ruby взял их из него), вы выполняете итерацию, как и другие «управляющие структуры», отправляя блок кода подходящему методу и, если хотите, можете сделать что прямо с коллекцией (думаю select:
):
aCollection select: [:item | item doSomething].
Итак, в Smalltalk (и Ruby) вы отправляете блок кода на итерацию; Python делает все наоборот, итерация отправляет значения в окружающий «вызывающий» код. Выглядит совсем по-другому, но в конце концов не очень сильно.
Первоклассные кодовые блоки означают, что Smalltalk не нуждается и не имеет операторов «контрольной структуры» и таких ключевых слов, как if
или while
: они могут быть выполнены путем отправки кодовых блоков в качестве аргументов соответствующих методов (например, ifTrue:
метод логических значений). (Ruby выбирает ключевые слова / операторы в дополнение к блокам кода первого класса; я бы сказал, что Python [[явно]] и Smalltalk [[неявно]] оба пытаются, как C, выполнить " предложить один способ выполнения операции ", в то время как Руби больше в школе Perl-ish" есть много способов сделать это ").
И хотя
оба, как говорят, динамически набираются, я
считаю, что Python не делает
динамический метод отправки. Это
исправить?
Нет, абсолютно неверно - Python интенсивно выполняет динамический метод отправки, в крайности . Рассмотрим для примера:
for i in range(10):
myobject.bah()
По семантике Python это выполняет 10 поисков для метода bah
в myobject
- на тот случай, если предыдущее выполнение метода вызвало myobject
полную внутреннюю реструктуризацию, так что его текущий bah
метод полностью отличается от предыдущего (для программиста может показаться довольно безумной вещью полагаться на такой яростный динамизм, но Python его поддерживает). Это причина, которая делает:
themethod = myobject.bah
for i in range(10):
themethod()
распространенная ручная оптимизация в коде Python - выполняет один динамический поиск перед циклом вместо 10 внутри цикла, по одному на ногу (это случай «постоянного подъема», поскольку компилятору запрещено делать «постоянный» сворачивание "себя" по экстремальным правилам Python для динамического поиска - если только он не может доказать, что он гарантированно безопасен, и на практике такое доказательство является слишком сложным, поэтому реализации Python обычно не беспокоятся).
Python использует унифицированные пространства имен: методы являются атрибутами объекта, как и любой другой, за исключением того, что они могут быть вызваны. Вот почему извлечение метода без его вызова (известного как «связанный метод»), установка ссылки на него в переменной (или сохранение его в списке или другом контейнере, возвращение его из функции, что угодно) является простым простая операция, как в приведенном выше примере с постоянным подъёмом.
Smalltalk и Ruby имеют отдельные пространства имен для методов и других атрибутов (в Smalltalk атрибуты, не относящиеся к методам, не видны за пределами собственных методов объекта), поэтому для «извлечения метода» и «вызова результирующего объекта» требуется более интроспективная церемония ( но общий случай диспетчеризации, таким образом, может быть несколько упрощен в некоторых случаях - в частности, «просто упоминание» метода без аргументов неявно вызывает его, в то время как в Python, как и в C, вызов явно выполняется добавлением скобок, в то время как «просто упоминая», ну ... «просто упоминает» об этом, делая его доступным для любых явных операций , включая вызов; -).