LINUX.ORG.RU

Декорирование блоков в CPython

 , , ,


0

2

Воскресный батхерт-разогрев перед началом рабочей недели. Очередной рассказ про «слабую логическую связанность, составленность из груды костылей, неподдатливость расширению», то есть " питоничность".

Как вы декорируете блоки кода в Python? Ну то есть все мы знаем, что можно декорировать функцию:

@decorator
def funcname(arg):
    pass

и даже декорировать класс:

@decorator
class classname:
    def __init__(self):
        pass

Но вот беда — как передать кусок кода в другую функцию? Вечная проблема лямбды в питоне, которая не решена до сих пор и никогда не будет решена:

>>> decorator(lambda: a = 2)
  File "<stdin>", line 1
SyntaxError: lambda cannot contain assignment

Мне стыдно, но я до сих пор не подозревал, что в лямбдах нельзя использовать присваивание. Я подозреваю, что я не один такой, на самом деле, потому что лямбды почти никто не использует — в том числе по этой причине.

«Хорошо, наш язык говно, но давайте не отчаиваться, с этим что-то можно сделать» — сказал когда-то Гвидо, и предложил:
https://www.python.org/dev/peps/pep-0343/ — PEP 343 — The «with» Statement

Этот чудесный костыль позволяет вам обрамить любой блок кода процедурами инициализации и финализации. Проблема — что мне делать, если я хочу обрамить блок кода сложнее, например, чтобы он оказался в цикле? То есть

for filename in filenames:
   with try_infinitely():
      print(open(filename, 'r').readlines())

В данном случае код должен пытаться бесконечно открывать и читать файл, пока не сможет это сделать. На питоне это можно написать как:

for filename in filenames:
    while True:
        try:
            print(open(filename, 'r').readlines())
        except Exception as e:
            print(e)
        else:
            break;

Но писать такую стенку каждый раз весьма утомительно. Как и заставлять юзверя объявлять вложенную функцию и передавать ее функции-декоратору, поскольку это будет нарушать обычную читаемость кода из-за того, что код вложенной функции будет выполняться позже своего объявления, в отличие от тех же лямбд JS, которые выполняются там, где определены. Чтобы была чуть более очевидна блевотность такого кода, я специально добавил цикл for filename in filenames снаружи:

for filename in filenames:
    @try_infinitely
    def nestedfunc():
        print(open(filename, 'r').readlines())
    nestedfunc()

или

@try_infinitely
def nestedfunc():
    print(open(filename, 'r').readlines())
for filename in filenames:
    nestedfunc()

Последнее, к моему удивлению, работает, потому что области видимости в питоне поделены на уровне функций, а не блоков, и потому filename будет видима в любом месте функции.

А хотелось бы чего-то простого и понятного, плана:

for filename in filenames:
    @try_infinitely:
        print(open(filename, 'r').readlines())

Чувствуете, как код сразу стал намного проще? Единственный выход, который я пока что вижу — это городить свой DSL через

source = inspect.get_source(func)
ast.parse(source, func.__code__.co_filename, 'exec')

К сожалению, питон из коробки не позволяет кормить AST декоратору, а сам AST он нигде не хранит, потому остается только парсить сырцы.

★★★★

Последнее исправление: byko3y (всего исправлений: 1)

Doing it wrong.

decorator(lambda: a = 2)

Почему не a = decorator(lambda: 2)()?

В данном случае код должен пытаться бесконечно открывать и читать файл, пока не сможет это сделать.

бесконечно

Ты точно программист?

eternal_sorrow ★★★★★
()
Последнее исправление: eternal_sorrow (всего исправлений: 1)

Я стараюсь не использовать декораторы в питоне. Легче от них не становится как и от всей функциональщины (разве что время работы функции прочекать), а вот геморроя и не очевидного поведения прибавится.

peregrine ★★★★★
()
Ответ на: комментарий от eternal_sorrow

decorator(lambda: a = 2)

Почему не a = decorator(lambda: 2)?

Ты же понимаешь, что это примитивный пример — я не буду вываливать сюда все 30 строчек кода, которая я хочу засунуть в эту лямбду и вложенные блоки с ними, как делают некоторые, вроде «пожалуйста, решите за меня домашку».

byko3y ★★★★
() автор топика
Ответ на: комментарий от peregrine

Я стараюсь не использовать декораторы в питоне. Легче от них не становится как и от всей функциональщины (разве что время работы функции прочекать), а вот геморроя и не очевидного поведения прибавится

Интересно, для чего же декораторы в стандартной либе?

egrep -r '^[[:space:]]*@[^(]*\(*' --include \*.py -ho ./Lib | sed 's/^ *//g' | sort | uniq -c | sort -n > rslt.txt

Топ хит парада:

 12 @functools.wraps(
 16 @abc.abstractmethod
 16 @patch.dict(
 16 @requires_tcl(
 20 @unittest.skip(
 28 @need_symbol(
 30 @patch(
 35 @add_standard_options(
 43 @patch.object(
 52 @unittest.skipIf(
 70 @unittest.skipUnless(
 82 @staticmethod
 99 @abstractmethod
326 @classmethod
382 @property

После сноса тестов:

 11 @functools.wraps(
 16 @abc.abstractmethod
 52 @staticmethod
 99 @abstractmethod
150 @classmethod
377 @property

Действительно, декораторы они использовать не любят.

А какие этому причины? Ну то есть я понимаю, что там есть проблемы с инспекцией, и, самое веселое, в питоне нет способа достать декорированную функцию. А вот потому что. Потому что декораторы как-то наспех прилепили. Забавно то, что в реализации этого самого classmethod используется тот факт, что внутри доступно намного больше сущностей, в том числе класс объекта, который оно успешно подменяет в аргументах.

Я предполагаю, что главная опасность декораторв таится в затруднении отладки, и, в частности, в неочевидном перепутывании параметров. А пеерпутывание параметров — это основная функций декораторов property, classmethod, staticmethod. Что же можно предложить взамен? Обычные функции, правильно? То есть, вместо

@text
@user
def create_post(user, text):
    backend.callCreatePost(user, text)

create_post(request)

делать

def create_post(request):
    user = get_user(request)
    text = get_text(request)
    backend.callCreatePost(user, text)

create_post(request)

Источник

Но когда мы отходим от однострочников, то внезапно оказываемся в той же проблеме, о которой было мое исходное сообщение — если мы захотим выполнить минимально сложную обработку в «декораторах». Например, если мы хотим не выполнять запрос в том случае, если пользователи не поддерживаются:

def create_post(request):
    if not users_supported:
        return
    user = get_user(request)
    text = get_text(request)
    backend.callCreatePost(user, text)

create_post(request)

То есть, код очень быстро раздувается. Особенно если таких функций много и эти строки придется везде повторять. А это могло бы выглядеть как-то так (микс питона и JS);

def create_post(request):
    return user(request, (user) => {
        return text(request, (text) => {
            return backend.callCreatePost(user, text)
        })
    })

create_post(request)

И тут уже можно использовать обработку исключений, условия, циклы, при этом мы четко видим поток аргументов — прошу обратить внимание, что request свободно передается во вложенные функции, во всех них он виден без каких-либо телодвижений. Мы заменили какие-то скрытые создания замыканий явными вызовами функций и явной передачей параметров.

byko3y ★★★★
() автор топика

С самописными декораторами такой подход:

  • Если декоратор убрать и поведение декорированного объекта не изменится, значит декоратор не мешает. Такой декоратор может какое нибудь кэширование делать, или просто регистрирует функцию/класс в каком то реестре. Также может устанавливать аттрибут-метку для метакласса, но поведение декорированного объекта от этого не меняется.

  • Если поведение меняется (декоратор перехватывает исключения или преобразует возвращаемое значение), то от таких декораторов только боль. Обычно осложняется тестирование кода. Потому что отделить теперь декоратор от оборачиваемого метода никак.

qaqa ★★
()
Ответ на: комментарий от byko3y

декораторы как-то наспех прилепили

В этом вообще весь питон - напихать побольше фич и костылей ad hoc. Это в общем-то удобно для разовых лабораторок, или в качестве бейсика 2.0 в диалоговом режиме как в старые добрые времена (привет датасаенсерам на юпитере).

Зря ты тратишь время, пытаясь выколупать какой-то смысл в этом говне.

no-such-file ★★★★★
()
Ответ на: комментарий от byko3y

Бесполезно сравнить питон с жс, это совершенно разные языки, пиши на жс раз он тебя устраивает. А ещё лучше возлюби Лисп.

anonymous
()
Ответ на: комментарий от qaqa

С самописными декораторами такой подход

.. если код ничего не делает — это хороший код. Если код что-то делает — это плохой код, поскольку его сложнее тестировать, он связан с остальным кодом.

byko3y ★★★★
() автор топика
Ответ на: комментарий от no-such-file

В этом вообще весь питон - напихать побольше фич и костылей ad hoc. Это в общем-то удобно для разовых лабораторок, или в качестве бейсика 2.0 в диалоговом режиме как в старые добрые времена (привет датасаенсерам на юпитере).
Зря ты тратишь время, пытаясь выколупать какой-то смысл в этом говне

Я вроде говорил уже, что питон как язык — это кусок дерьма, который нереально исправить. Но нереально исправить его благодаря его единственному «преимуществу» — наличие большого числа готовых библиотек от гугла. Готовых библиотек, которые на другой язык придется портировать не год и не два.

А смысл есть — построить мостик между старым наследием и чем-то новым, у которого есть будущее. И я снова и снова прихожу к тому, что имеющийся интерпретатор руками и ногами упирается какому бы то ни было расширению и усовершенствованию, а потому возникает необходимость в DSL. Радует только то, что абсолютно та же проблема возникла и у других проектов, которые создают CPython-несовместимые диалекты питона, и даже вообще не похожие на питон DSL-и для решения проблем, которые в этом «бейсике 2.0» нерешаемы в принципе. А пока питон весит в топах ЯП — это кому-нибудь, да будет нужно.

Ты бы лучше рассказал вот что: если это такое говно, то почему на него налетело столько мух? Я до конца этого не понимаю, и не понимаю, например, почему это место не занял Руби... или PHP, которые очень даже популярен в своей нише... или Свифт, который вроде как развивается и получает много поддержки — даже целый TensorFlow под него перепилили, и ядро под юпитер для этого TensorFlow сделали.

byko3y ★★★★
() автор топика
Ответ на: комментарий от anonymous

https://stackoverflow.com/questions/6282042/assignment-inside-lambda-expressi...
lambda: (
message := «Hello world»,
sys.stdout.write(message + «\n»)
)

Охренеть, еще один DSL, кто бы мог подумать? Обрамление блоков в скобочки, строки разделены запятыми, оператор присваивания паскалевый — питон играет новыми красками!

byko3y ★★★★
() автор топика
Ответ на: комментарий от anonymous

Бесполезно сравнить питон с жс, это совершенно разные языки, пиши на жс раз он тебя устраивает

Спасибо, пишу на JS на нынешнем рабстве.

А ещё лучше возлюби Лисп

Не проси. Лисп из топ 3 ушел на дно, где ему и место. Подход к организации разработки на языке у Common Lisp мне понравился, сразу видно много лет проработанности языка, куча исправленных ошибок, но! Скобочки из языка нужно убрать — и тогда на нем можно начинать писать.

byko3y ★★★★
() автор топика

decorator(lambda: a = 2)

decorator(funcname)

<какая-то лапша>

def nestedfunc():
    print(open(filename, 'r').readlines())
try_indefinitely(nestedfunc)

код вложенной функции будет выполняться позже своего объявления, в отличие от тех же лямбд JS, которые выполняются там, где определены

lolwut

t184256 ★★★★★
()
Ответ на: комментарий от byko3y

Неспособность человека в, ктобымогподумать, синтаксис — лучший детектор. Судя по шапке и этому комменту, она у тебя систематическая.

Если ты дальше синтаксиса не видишь, что ж ты с ним делать дальше будешь?

t184256 ★★★★★
()
Ответ на: комментарий от t184256

Неспособность человека в, ктобымогподумать, синтаксис — лучший детектор

А ты с лиспом знаком? Как ты думаешь, почему из него 60 лет подряд не могут убрать скобочки? Раз уж ты видишь подальше меня.

byko3y ★★★★
() автор топика

На самом деле, with это сахарок для try-finally, потому ожидать от него чего то большего, это как минимум странно

Твой tryInfinitely, вполне можно выразить как

x = try_infinitely(labmda : open(filename, 'r').readlines())

да, без права записи в scope, но этим грешат все лямбды в языках без поддержки ссылок

Вот у меня больше претензий к самой объектной модели python, например

class MyService(Service):

    def post_init(self):
        self.init=True

    def post_init(self):
        self.asd=1

Вполне валидный код

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

Зато у них есть множественное наследование

anonymous
()
Ответ на: комментарий от byko3y

Профессионального опыта разработки на лиспе не имею, концептуально считаю себя знакомым. Писал когда-то интерпретатор, естественно; как-то вел в универе курс, где надо было писать на Clojure.

t184256 ★★★★★
()
Ответ на: комментарий от anonymous

да, без права записи в scope, но этим грешат все лямбды в языках без поддержки ссылок

Чиво?

> lambda = () => {
... let a = 2;
... console.log(a)
... }
[Function: lambda]
> lambda()
2

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

Причинно-следственность нарушена. Потому что нужно было бы задаться вопросом «почему это сделано так, как сделано, и кто это сделал?». Для Гвидо такого вопроса не существует, потому питон таков, каков он есть. Язык можно свети к «я сказал!». Почему корявая объектная модель? Я сказал. Почему нет адекватной поддержки лямбд? Я сказал. Почему язык состоит из десятка разрозненных DSL, не похожих друг на друга? Я сказал.

byko3y ★★★★
() автор топика
Ответ на: комментарий от byko3y

.. если код ничего не делает — это хороший код. Если код что-то делает — это плохой код, поскольку его сложнее тестировать, он связан с остальным кодом.

Это такой сарказм? :) Я говорю, что тестировать код который обернут декоратором, это геморой. Нельзя декоратор убрать. Это как часть реализации становится. Очень дико неудобно.

qaqa ★★
()
Ответ на: комментарий от t184256

Профессионального опыта разработки на лиспе не имею, концептуально считаю себя знакомым. Писал когда-то интерпретатор, естественно; как-то вел в универе курс, где надо было писать на Clojure

Мне бесит, что ты имеешь крайне поверхностное представление о языке, но именно в этом упрекаешь почему-то меня. Фраза про скобки была на самом деле сарказмом, намекающим на другие, более значимые недостатки лиспа, результатом которых стала такая привязанность к обилию скобок в языке.

byko3y ★★★★
() автор топика
Ответ на: комментарий от qaqa

Я говорю, что тестировать код который обернут декоратором, это геморой. Нельзя декоратор убрать. Это как часть реализации становится. Очень дико неудобно

Ну а ты пробовал когда-нибудь убирать строчки из функций и тестировать код без них? Это что ж получается по твоей логике: строчки кода — зло?

byko3y ★★★★
() автор топика
Последнее исправление: byko3y (всего исправлений: 1)
Ответ на: комментарий от byko3y

Это что ж получается по твоей логике: строчки кода — зло?

Ептить, коллега, не путайте одно с другим. Если код выглядит так

class Class:
   def func(...):
       ...


class DecoratedClass:
    def __init__(obj):
        self._obj = obj

    def func(arg, ...):
        ...
        result = self._obj.func(arg, ...)
        ...
        return result

obj = Class()
decorated_obj = DecoratedClass(obj)

decorated_obj.func(kwargs)

или вот так

def func(...):
   ...


def decorated_func(a_func, a_func_kwargs):
    ...
    result = a_func(**a_func_kwargs)
    ...
    return result

result = decorated_func(func, kwargs)

то можно независимо протестировать все куски. Интеграционный тест тоже нужен, но 1 достаточно.

Когда сделано вот так

@a_func_decorator
def func(...):
   ...

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

qaqa ★★
()
Последнее исправление: qaqa (всего исправлений: 3)
Ответ на: комментарий от byko3y

питон весит в топах ЯП

Он потому и висит в топах, что им пользуются не программисты. Пользовательская база получается шире, чем у какого-нибудь голанга или ноды.

почему на него налетело столько мух

Как бейсик, или матлаб на стероидах он удобен. Более удобен чем всё остальное.

почему это место не занял Руби… или PHP, которые очень даже популярен в своей нише

Что касается пыха, то он в своей нише никуда и не девался, как был топ, так и остался. Руби, честно говоря, вообще не пришей кобыле хвост. Ещё когда он появился, я не понимал, зачем нужен ещё один язык без каких-то амбиций. ООП это хорошо, но нафига нужен ruby когда уже есть smalltalk мне лично не ясно. Если бы не рельсы, которые явили собой удачную концепцию, никак не связанную однако с языком, то руби уже давно бы окочурился.

Питон, КМК просто изначально подавался как язык для академической среды, а потом люди которые на нём учились притащили его в свои сферы деятельности. В своё время у нас был популярен Паскаль и там где сейчас Питон, народ использовал тот самый Паскаль: писали программы для расчётов всякой хрени, АРМы и т.п. Даже в учебники это попадало, я имею в виду профильные, не про программирование.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от byko3y

почему из него 60 лет подряд не могут убрать скобочки

Что значит не могут? Не хотят! Я честно вообще не понимаю, почему людей так волнуют скобочки. Никто же не ругается что в выражениях часто куча скобок, типа b*(a+c*(d+x)) т.п. Или скажем, if (), for()… в питоне вон убрали. Результат как бы не очень.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от qaqa

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

По алгоритму разницы нет, делает код почти то же самое везде и декоратор можно тестить отдельно. Разве что код декоратора может быть менее очевидным, поскольку возвращает замыкание.

byko3y ★★★★
() автор топика
Ответ на: комментарий от no-such-file

Если бы не рельсы, которые явили собой удачную концепцию, никак не связанную однако с языком, то руби уже давно бы окочурился

Подсказка: Apple. А рельсы не нужны.

В своё время у нас был популярен Паскаль и там где сейчас Питон, народ использовал тот самый Паскаль: писали программы для расчётов всякой хрени, АРМы и т.п. Даже в учебники это попадало, я имею в виду профильные, не про программирование

Мне довелось столкнуться с научными расчетами на паскале. Это такой адище, что аж страшно вспоминать. Логика мышления и принятия решения этими людьми чудовищно далека от моей.

byko3y ★★★★
() автор топика
Ответ на: комментарий от byko3y

Смехотворное задопедалирование от человека с твоими рассуждениями об убирании скобочек из лиспа или твоим соотношением познания/критика в отношении синтаксиса Python.

t184256 ★★★★★
()
Ответ на: комментарий от byko3y

По алгоритму разницы нет,

Вы хотели сказать, клиенту нет разницы, если его бизнесс задача решена? А вот программисту как раз есть разница, как код организован.

декоратор можно тестить отдельно

его можно тестить отдельно, а вот декорируемую функцию/метод уже нет. В крайнем случае можно изучить кишки декоратора и что-нибудь запатчить, чтобы его по-факту отключить. Даже это иногда непросто сделать - был соответсвующий опыт. И все это гимор на ровном месте.

qaqa ★★
()
Последнее исправление: qaqa (всего исправлений: 1)
Ответ на: комментарий от no-such-file

Что значит не могут? Не хотят! Я честно вообще не понимаю, почему людей так волнуют скобочки. Никто же не ругается что в выражениях часто куча скобок, типа b*(a+c*(d+x)) т.п. Или скажем, if (), for()… в питоне вон убрали. Результат как бы не очень

Ты смешиваешь отсутствие архитектуры, которое убило питон, с простотой синтаксиса. Вообще, я думаю, что где-то здесь кроется разгадка успеха питона в академической среде. Ведь питон откуда-то оттуда вышел. То есть, много фич, киборг с тремя головами, восемью ногами, глазами на затылке, на лобке и обоих ягодицах — всего по чуть-чуть, при этом показательная аскетичность, этот киборг ведет ЗОЖ и вегетарианец.

Как в популярной музыке, где идол обязательно должен быть сверхчеловеком без вредных привычек, безупречно выглядеть 24/7, чтобы на камеру вставать из постели в макияже и прическе. А копнешь чуть глубже — выяснится, что это наркоман-зоофил, который по выходным резвится с лощадями под коксом. Ну то есть этот язык не простой (со стандартной либой даже сложнее C++ с ее стандартной либой), без лишних фич лучше, чем с ними, при этом необучаем, за 30 лет не смог в многопоток и быстрое выполнение.

То есть, я клоню к печальной мысли о том, что только плохой ЯП может стать популярным, то есть, публика требует несовместимых и несостоятельных фич, которые убьют любой ЯП,

Кстати, Дейкстра, 1972 год:

«Another lesson we should have learned from the recent past is that development of ‘richer’ or ‘more powerful’ programming languages was a mistake in the sense that these baroque monstrosities, these conglomerations of idiosyncrasies, are really unmanageable both mechanically and mentally»

https://www.cs.utexas.edu/users/EWD/transcriptions/EWD04xx/EWD473.html — 1975:

«The student's attention is almost entirely absorbed by becoming fully familiar with the ideosyncrasies of the various languages and is made to believe that the more of these ideosyncrasies he understands, the better a programmer he will be. But no one tells him that all those bells and whistles —those so-called „powerful features“— belong more to the problem set than to the solution set. Nobody tells him that at best he will become an expert coder of trivial algorithms, and that his difficulties will never arise from the problem itself, but always from the funny way the (usually given) algorithm has to be coded.»

https://www.cs.utexas.edu/users/EWD/transcriptions/EWD06xx/EWD667.html — 1976

«Some people found error messages they couldn't ignore more annoying than wrong results, and, when judging the relative merits of programming languages, some still seem to equate „the ease of programming“ with the ease of making undetected mistakes.»

https://www.cs.utexas.edu/~EWD/transcriptions/EWD10xx/EWD1036.html — 1988

«A number of these phenomena have been bundled under the name „Software Engineering“. As economics is known as „The Miserable Science“, software engineering should be known as „The Doomed Discipline“, doomed because it cannot even approach its goal since its goal is self-contradictory. Software engineering, of course, presents itself as another worthy cause, but that is eyewash: if you carefully read its literature and analyse what its devotees actually do, you will discover that software engineering has accepted as its charter »How to program if you cannot.«»

То есть, «питон» с индустрией произошел уже за 20 лет до появления CPython. Ключевые факторы:

 — склонность академической среды иметь больше ног (знаний), а не быстрее бегать (уметь их применять);
 — Software Engineering, то есть, готовые методики программирования, представляют костыли, которые помогают на этих восьми ногах хотя бы как-то передвигаться для тех, кто бегать не научится никогда, и чем хуже человек способен программировать, тем больше ему нужно инструментов для программирования;
 — чисто школьная установка «если ошибку никто не заметил, то её не нет», которая, конечно, не является решающей, но придает характерный аромат, который вы можете отчетливо уловить в отдельных ЯП.

PS: совсем забыл написать, что мне приходилось самому сталкиваться с тем, что 95% нанимающих тебя на работу людей либо происходят из этой академической среды, либо находятся под сильным влиянием онной — и потому ждут, что ты налезешь на конкретные шаблоны. А от простых клиентов-потребителей мое мышление еще дальше. Вот у меня и горит от того, что я не вписываюсь в рыночек. Хочется великого, а тебе дают вилку в руки и отправляют чистить говно.

byko3y ★★★★
() автор топика
Последнее исправление: byko3y (всего исправлений: 2)
Ответ на: комментарий от qaqa

его можно тестить отдельно, а вот декорируемую функцию/метод уже нет. В крайнем случае можно изучить кишки декоратора и что-нибудь запатчить, чтобы его по-факту отключить. Даже это иногда непросто сделать - был соответсвующий опыт. И все это гимор на ровном месте.

Я выше уже отвечал, что вызовы функций. действительно, проще и чище, чем передача ссылок на замыкания:

Декорирование блоков в CPython (комментарий)

Другое дело, что декораторы вполне себе тестируемы, а тот факт, что из декоратора нельзя выковырять задекорированную функцию... ну что же, все вопросы в Гвидо, тут как бы сама идея технологии не при чем. И вот это уже настоящая проблема. Люди решают ее — делают раскрываемые декораторы схороняющие указатель на декорированную функцию в атрибуте возвращаемого замыкания, и дальше в коде тестирования остается рекурсивно проходить по этим атрибутам, таким образом получая исходную функцию независимо от числа декораторов.

byko3y ★★★★
() автор топика
Ответ на: комментарий от byko3y

только плохой ЯП может стать популярным

Я бы сказал, что только достаточно плохой, но не хуже. Этот факт известен уже очень давно, пресловутое regression towards mediocrity. С другой стороны, так устроен мир. Пытаться тут что-то менять бессмысленно.

no-such-file ★★★★★
()

Ну вообще для этих целей обычно используется with. Не понимаю, почему он тебе не подошел. Вот в чем тут проблема?

for filename in filenames:
   with try_infinitely():
      print(open(filename, 'r').readlines())

Ты как-то криво сделал менеджер контекста, что он в цикле ломается или что?

Aswed ★★★★★
()
Ответ на: комментарий от Aswed

Ну вообще для этих целей обычно используется with. Не понимаю, почему он тебе не подошел. Вот в чем тут проблема?
Ты как-то криво сделал менеджер контекста, что он в цикле ломается или что?

Проблема в том, что если внутри цикла произойдет ошибка, то файл из списка окажется необработанным. А смысл try_infinitely заключается в том, чтобы бесконечно пытаться его открыть, пока не получится.

byko3y ★★★★
() автор топика
Ответ на: комментарий от byko3y

да ладно, не нравится - не пользуй, вон в перле батареек не меньше, это во-первых, а во-вторых, бери любой другой понравившийся язык, освой для него написания биндингов и втаскивай любые необходимые нативные библиотеки, я так как раз для питона делаю

EugeneBas ★★
()
Ответ на: комментарий от EugeneBas

да ладно, не нравится - не пользуй, вон в перле батареек не меньше, это во-первых, а во-вторых, бери любой другой понравившийся язык, освой для него написания биндингов и втаскивай любые необходимые нативные библиотеки, я так как раз для питона делаю

Так и не пользуюсь, так и беру любой другой. Проблема в том, что я могу освоить любой язык, чем, к сожалению, успешно пользуюсь. Но все-таки хочется какой-то социальной и коммерческой реализации, для чего нужно как минимум оглядываться на мейнстрим. А мейнстрим у нас — это питон. Более-менее приемлимый язык с нуля может сделать много кто, а из говна конфету — единицы.

PS: по поводу биндингов — это путь вникуда. Большинство биндингов питона на самом деле не делают ничего, а только помогают выполнять те же функции из языка быстрее.

byko3y ★★★★
() автор топика
Последнее исправление: byko3y (всего исправлений: 1)
Ответ на: комментарий от byko3y

Ты хочешь обернуть блок кода в цикл не написав сам цикл? Ты уверен что это то что тебе нужно? Ещё не ясно в чём проблема сделать свою функцию для open с N попыток.

anonymous
()
Ответ на: комментарий от byko3y

по поводу биндингов — это путь вникуда. Большинство биндингов питона на самом деле не делают ничего, а только помогают выполнять те же функции из языка быстрее.

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

А вообще биндинг позволяет не дублировать либу на скриптовом языке, если она уже существует в нативном виде. Это как раз сценарий для языка несколько менее популярного, чем питон.

EugeneBas ★★
()
Ответ на: комментарий от byko3y

Интересно, для чего же декораторы в стандартной либе?

Извращенцы. Ну и вообще есть практика всё в стандартную либу запихнуть чтобы пример был как это можно использовать.

А какие этому причины?

Баланс нужен между инструментами и их количеством. Слишком много инструментов тоже плохо и C++ тому пример и назидание. Ну и я не вижу достаточно весомой причины, кроме использования декораторов как временного костыля при отладке, чтобы им пользоваться.

Но когда мы отходим от однострочников

То могли бы записать весь код несколько проще:

def create_post(request):
    backend.callCreatePost(request.user, request.text)
create_post(request)
Так что пример максимально плохой. Он возникает когда request вместо объекта класса с конструктором и нужными полями является какой-то непонятной фигнёй, за само появление которой в коде надо бить по рукам. Больно. Вытаскивать вот эти вот user и text надо когда нужна какая-то серьёзная обработка.

И да, последний пример у тебя как по мне максимально не читабелен. Код должен легко читаться, а не быть максимально компакнтым.

peregrine ★★★★★
()
Ответ на: комментарий от no-such-file

Он потому и висит в топах, что им пользуются не программисты. Пользовательская база получается шире, чем у какого-нибудь голанга или ноды.

на ноде такое говно пишут, ты бы только видел. 2 года назад параллельно нам работала команда которая решала задачку на ноде, решили. Но у меня глаза вытекли и от их кода и от решения. Нифига они не программисты кстати, у ноды такой же низкий порог вхождения, даже ниже если честно, другое дело что нода даёт больше возможностей писать говнокод.

peregrine ★★★★★
()
Ответ на: комментарий от anonymous

Ты хочешь обернуть блок кода в цикл не написав сам цикл? Ты уверен что это то что тебе нужно? Ещё не ясно в чём проблема сделать свою функцию для open с N попыток

Очередной раунд «вам это не нужно». Нет, мне это нужно. Нет, никто не будет переписывать весь код из-за моей хотелки.

byko3y ★★★★
() автор топика
Ответ на: комментарий от no-such-file

Ты не поверишь. Деньги платят за решение задачек бизнеса, а не за красивый код написанный по феншую на «правильном» языке программирования. А профессионал от любителя отличается тем, что получает деньги за то что он делает, а не тем что он делает это лучше или хуже или не так как любитель.

peregrine ★★★★★
()
Ответ на: комментарий от peregrine

И да, последний пример у тебя как по мне максимально не читабелен. Код должен легко читаться, а не быть максимально компакнтым

Для питониста? Да, нечитабелен. Как у JS-ник со стажем, у меня лично не возникает проблем с чтением. Но да, они были вначале, потому что с ходу нужно еще привыкать к лисповому изобилию безликих скобочек — но я привел пример чисто чтобы показать идею, не обязательно синтаксис должен быть именно таким.

def create_post(request):
backend.callCreatePost(request.user, request.text)
create_post(request)

get_user и get_text могут быть весьма нетривиальными функциями, которые придется приколачивать через (сюрприз) декоратор @property к запросу. При этом по прежнему непонятно, что делать при исключениях и условном выполнении.

byko3y ★★★★
() автор топика
Ответ на: комментарий от byko3y

Научные расчёты всегда ужасны и не очевидны, особенно когда что-то новое считают. На самом деле станет легче понимать почему так, а не как правильно, если станет понятно что в случае R&D далеко не всегда сразу есть готовая теория и сначала присматриваются к данным с которыми работают, что-то проверяют, тестируют, а потом куски кода которые были для тестирования и проверки какой-либо гипотезы просто выдираются с мясом, но архитектуру проекта они уже успели испортить, так как надо не переписывать красиво, а дальше ресёрчить, потому что за переписывание и трату на это времени у дорогого и узкопрофильного специалиста по мозгам должны получить все, начиная от специалиста, кончая его начальником. Потом наймут царя сишки за 100 рублей и он всё перепишет чтобы красиво было.

peregrine ★★★★★
()
Ответ на: комментарий от byko3y

Ты смешиваешь отсутствие архитектуры, которое убило питон

Сходи рынок посмотри или гитхаб. Питон живее всех живых вместе с убогой нодой и пых-пыхом.

peregrine ★★★★★
()
Последнее исправление: peregrine (всего исправлений: 1)
Ответ на: комментарий от peregrine

Нифига они не программисты кстати

Ты не понял, они-то решали программистскую задачку. А на питоне решают в т.ч. и не программистские задачки, а дивергенцию ротора по контуру тензора в вакууме. Поэтому клиентура питона шире, чем ИТ-тусовочка.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 2)
Ответ на: комментарий от peregrine

Деньги платят за решение задачек бизнеса

Вопрос был как бы не об этом, а о причинах, почему для решения берут питон. Платят же не конкретно за питон, а за «решение задачек».

no-such-file ★★★★★
()
Ответ на: комментарий от byko3y

Для питониста? Да, нечитабелен. Как у JS-ник со стажем

Дядь, я больше 11 лет код пишу из которых питон только 3 года использую и то не могу сказать что только питон, приходится и разбавлять его крестиками и на баше надо иногда портянку написать, а иногда надо js-лапшу посмотреть и в качестве хобби с LUA повозиться и попилить моды на ней, а в прошлом ещё и C# с java лежат из которых C# основным был года 4, а в java заглядывал только чтобы одну программку под android-ом переделать. Конечно за 11 лет онли js можно привыкнуть к нему и сказать что это топ язык, но нет, js - это плохой язык. Народ вон и к C++ привыкает и ничего.

Моё мнение:

C# - хороший язык

Java - хороший язык

C++ - не хороший язык, но безальтернативен по 2 причинам: глубоко окопался в компьютерах как и его родственник C, быстрый и с ООП.

Python - хороший язык для программиста, немного медленный, требует батареек в узких местах, как клей идеален

Rust - идея лучше чем у C, но инфраструктуры нету, уступает C++ в производительности и применимости в очень больших проектах.

LUA - хорош для компа, плох для программиста, практически безальтернативен из-за производительности скриптов на нём

BASH - плохой язык, живёт только в юниксах ибо дефолт и много наработок на все случаи жизни

JS - плохой язык, живёт за счёт веба более известного как всемирная помойка, получил распространение из-за отличного интерпретатора V8 в который гугл влил очень много долларов ради браузера гугл хром

peregrine ★★★★★
()
Ответ на: комментарий от no-such-file

Ты не понял, они-то решали программистскую задачку.

Нет конечно. Они решали прикладную задачку на основе статистики, но поскольку пара человек в их команде когда-то работала с вебом, они взяли для этого знакомый им JS. Графики красивые нарисовали конечно, благо веб способствует, но на этом всё и закончилось.

peregrine ★★★★★
()
Ответ на: комментарий от no-such-file

Потому что он позволяет быстро и небольшими усилиями решать огромный кусок задачек бизнеса. Чего нельзя сказать, например, о C++. Там будет медленно и трудно, но зато можно решить больше задачек, учитывая те в которых критична производительность/очень дорого железо.

peregrine ★★★★★
()
Ответ на: комментарий от peregrine

прикладную задачку на основе статистики, но поскольку пара человек в их команде когда-то работала с вебом, они взяли для этого знакомый им JS

Оо, ну это какой-то уникальный случай. И скорее подтверждает мой тезис о популярности питона: более вероятно кто-то в команде слушал курс с примерами на питоне, или книжку читал.

но на этом всё и закончилось

В такого рода задачах, продолжение и не требуется. Картинки – это и есть конечный результат. Код можно выбрасывать, он больше не нужен.

Потому что он позволяет быстро и небольшими усилиями решать огромный кусок задачек бизнеса

Не быстрее любой другой скриптухи. Разница в скорости достигается только тем, что решатили умеют решать только на питоне. Вопрос был в том, почему так. Ответ: потому что их так научили.

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.