Найти - Пользователи
Полная версия: Как добавить метод в существующий внешний класс (модуль)?
Начало » Python для новичков » Как добавить метод в существующий внешний класс (модуль)?
1
alibek
Не соображу, как сделать.
Хочу к стандартному логгеру добавить уровень логгирования TRACE=5 и соответствующий метод trace().
Вроде бы должно быть примерно так:
 class MyLogger(logging.Logger):
    TRACE = 5
    def trace(self, msg, *args, **kwargs):
        if self.getEffectiveLevel < logging.TRACE:
            return self.debug(msg, *args, **kwargs)
logging.setLoggerClass(MyLogger)
logging.basicConfig(level=MyLogger.TRACE)
log = logging.getLogger(__name__)
Но не работает.
Не подскажите, как правильно сделать?
alibek
В таком виде работает:
 class MyLogger(logging.Logger):
    logging.TRACE = 5
    def trace(self, msg, *args, **kwargs):
        if self.getEffectiveLevel() <= logging.TRACE:
            return self.debug(msg, *args, **kwargs)
logging.setLoggerClass(MyLogger)
log = logging.getLogger(__name__)
log.setLevel(logging.TRACE)
log.trace('* trace')
log.debug('* debug')
log.info('* info')
Но не знаю, насколько это корректно.
Можно ли таким образом переопределять свойства и константы модуля?
alibek
Вот такой вариант вроде бы правильный:
 class MyLogger(logging.Logger):
    logging.TRACE = 5
    logging.addLevelName(logging.TRACE, 'TRACE')
    def _trace(logger, message, *args, **kwargs):
        if logger.isEnabledFor(logging.TRACE):
            logger._log(logging.TRACE, message, args, **kwargs)
    logging.Logger.trace = _trace
logging.setLoggerClass(MyLogger)
logging.basicConfig(format='%(asctime)s [%(name)s:%(process)d] |%(levelname)s| %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
log = logging.getLogger(__name__)
log.setLevel(logging.TRACE)
log.trace('* trace')
log.debug('* debug')
log.info('* info')
py.user.next
alibek
Вот такой вариант вроде бы правильный
А где ты его взял? Написан бред явный.
alibek
Тем не менее он работает именно так, как мне требуется; поведение полностью идентично остальным уровням логгирования.
Что именно там бредового?
py.user.next
alibek
Вот такой вариант вроде бы правильный:
 class MyLogger(logging.Logger):
    logging.TRACE = 5
    logging.addLevelName(logging.TRACE, 'TRACE')
    def _trace(logger, message, *args, **kwargs):
        if logger.isEnabledFor(logging.TRACE):
            logger._log(logging.TRACE, message, args, **kwargs)
    logging.Logger.trace = _trace
logging.setLoggerClass(MyLogger)
logging.basicConfig(format='%(asctime)s [%(name)s:%(process)d] |%(levelname)s| %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
log = logging.getLogger(__name__)
log.setLevel(logging.TRACE)
log.trace('* trace')
log.debug('* debug')
log.info('* info')
Ну вот ты вот это написал и говоришь “это правильный код”. Вообще-то, в классе никакие операторы нельзя выполнять. Максимум там можно имена какие-то присваивать (перепривязывать имена). Такую бредятину могла выдать только ChatGPT, поэтому у меня и закрались сомнения, а не через неё ли ты пишешь код и вещаешь потом здесь, что он правильный. Она же ахинею пишет и утверждает, что это всё правильно, что она пишет там.
alibek
py.user.next
Вообще-то, в классе никакие операторы нельзя выполнять.
Синтаксически — можно. Если что-то на самом деле нельзя, то об этом скажет Python.
Если про “бред” и “нельзя” было написано только из-за ваших привычек и вашего представления о том, как должен быть написан код, то так и пишите — “я считаю неправильным выполнять операторы в основном теле класса, перенесите их в конструктор или метод инициализации”. И я отвечу “спасибо, учту” или “плевать”.
Тем более, что в данном случае никаких проблем не вижу, все манипуляции идут со статическими свойствами модуля.
py.user.next
Не, это не я так считаю. Тут ещё один пацан считает, что надо там по-нормальному всё делать. Но тот пацан, какой-то вот лох, написал как раз этот logging, которым ты пользуешься. Ну иди поспорь ещё с ним. Ты же умный, а он дурак.
python.org. logging
logging.setLoggerClass(klass)

Tells the logging system to use the class klass when instantiating a logger. The class should define __init__() such that only a name argument is required, and the __init__() should call Logger.__init__(). This function is typically called before any loggers are instantiated by applications which need to use custom logger behavior. After this call, as at any other time, do not instantiate loggers directly using the subclass: continue to use the logging.getLogger() API to get your loggers.
Вот для тупорылых написано: сделайте в __init__'е это всё, вызовите родительский __init__ ещё, чтобы ничего не сломалось.

alibek
Если про “бред” и “нельзя” было написано только из-за ваших привычек и вашего представления о том, как должен быть написан код, то так и пишите — “я считаю неправильным выполнять операторы в основном теле класса, перенесите их в конструктор или метод инициализации”.
Тебе же говорят, ты просто дурак.

alibek
Тем более, что в данном случае никаких проблем не вижу
А кто ты такой, чтобы видеть? У тебя мозгов нет. Тебе же говорят: сначала нужно прочитать всё, а потом делать. В итоге ты делаешь какую-то хуйню, потом ещё это с умным видом постишь везде, а потом ещё споришь со всеми, когда тебе в лицо говорят, что ты хуйню сделал. Потом тебе говорят, что ты говнодел и всё. А потом ты обижаешься на всех. Так что сиди обиженный и дальше. В этом виноват только ты сам.

Если человек дебил, то это надолго.
alibek
Мда.
Ладно, попробую еще раз.

Ранее вы написали про мой код, что это “бред” и так “нельзя”.
А когда я попросил пояснить, заявили что “в классе никакие операторы нельзя выполнять”.
Разумеется, это заявление ошибочно.

Во-первых, использование оператора присвоения в теле класса — это не просто нормально, это распространенный сценарий.
Если моих слов недостаточно, можете посмотреть исходный код стандартных классов питона, например logger: https://github.com/python/cpython/blob/main/Lib/logging/__init__.py
Во втором же классе PercentStyle идут строки:
     default_format = '%(message)s'
    asctime_format = '%(asctime)s'
    asctime_search = '%(asctime)'
Если мало, то можете поискать уже самостоятельно, таких примеров достаточно.
Таким образом два случая использования оператора присвоения в моем коде (logging.TRACE = 5, logging.Logger.trace = _trace) и декларация функции (def _trace) это не “бред”, а вполне рабочая и используемая конструкция.

Если следовать академизму, то вызов метода в теле класса (logging.addLevelName) наверное действительно можно было перенести к конструктор.
Но если посмотреть код этого метода (https://github.com/python/cpython/blob/main/Lib/logging/__init__.py#L156), то это не метод класса, а функция в теле модуля, которая вдобавок делает два присовения переменным _levelToName и _nameToLevel. То есть по сути, если эту функцию “развернуть”, то это все то же присвоение.
Поэтому не вижу никакой проблемы в том, чтобы вызывать эту функцию в теле класса.

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

Очевидно, что интернет играет в вашей жизни социальную функцию.
Вероятно, вы рассматриваете данный форум в каком-то смысле как свою территорию.
А там, где есть территория и коллектив, есть и иерархические игры.
Возможно вы думаете, что любая ответная реакция новичка на ваш совет, отличная от благодарности и признательности, является покушением на ваше место в иерархии, на которое, разумеется, нужно дать мгновенный и жесткий отпор.
Поэтому ваши агрессивные заявления про “бред” на самом деле не про корректность (или некорректность) программного кода, а автоматическая реакция с попыткой заранее обесценить любые аргументы соперника, объявив их несущественными и/или ложными.
Реакция поспешная и ошибочная, но признать ошибку вы уже не можете, ведь это публичное место и вдруг другие участники форума подумают, что Акела промахнулся.
Отсюда и пустая болтовня и софистика, чтобы отвлечь от своей ошибки и не допустить падения авторитета.

Так вот, хочу вас успокоить.
Эти иерархические игры на самом деле неинтересны 99% участниками форума, которые в среднем написали менее 5 сообщений за все время.
И я тоже не покушаюсь на ваше место в иерархии, пусть у меня к этому моменту будет опубликовано 15 сообщений, что втрое больше среднего по форуму.
Я нахожу глупым играть в такие игры в интернете на публичном форуме (который вдобавом специализирован на языке программирования), поскольку никакой практической пользы от них я не вижу.
Если вы хорошо знаете Python — это хорошо для вас. Если при ответах новичкам вы будете давать корректные ответы без личных выпадов — как ни странно, это тоже будет хорошо для вас.
Хотя, мне безразлично.
py.user.next
alibek
Во втором же классе PercentStyle идут строки:
  
default_format = '%(message)s'
asctime_format = '%(asctime)s'
asctime_search = '%(asctime)'
Это присваивание констант на уровне класса. Эти операции ничего не меняют нигде. Так же, как и регулярное выражение, которое там компилируется дальше, ни на что не влияет и даёт константный объект.

  
>>> import re
>>> 
>>> pat = re.compile('.')
>>> 
>>> pat
re.compile('.')
>>> type(pat)
<class '_sre.SRE_Pattern'>
>>> dir(pat)
['__class__', '__copy__', '__deepcopy__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'findall', 'finditer', 'flags', 'fullmatch', 'groupindex', 'groups', 'match', 'pattern', 'scanner', 'search', 'split', 'sub', 'subn']
>>> pat.x = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: '_sre.SRE_Pattern' object has no attribute 'x'
>>> pat.match = lambda: 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: '_sre.SRE_Pattern' object attribute 'match' is read-only
>>>

Так что ты перепутал немножечко. А почему перепутал? А потому, что ты не шаришь вообще в этой теме, так как ни одной книги не прочитал, в которых всё это 100500 раз описано со всех сторон.

alibek
Таким образом два случая использования оператора присвоения в моем коде (logging.TRACE = 5, logging.Logger.trace = _trace) и декларация функции (def _trace) это не “бред”, а вполне рабочая и используемая конструкция.
Даже несмотря на то, что в logging.TRACE в твоём чудесном коде, причём “правильном” (как ты выразился изначально и упёрся потом, когда тебя носом в это ткнули, что это неправильно вообще-то), ей присваивается константа, это тоже неправильно. Это вообще твой уровень показывает, что ты находишься где-то на непонимании даже того, чем вредны глобальные переменные. То есть это воообще новичковый пробел в знаниях. Почему это нельзя делать - по той же самой причине, почему и глобальные переменные нельзя делать. У них похожие механизмы генерации бардака и неразберихи.

То есть у тебя один модуль влияет на внутреннее состояние другого модуля прямо при своём возникновении. То есть если таких модулей сделать штук пять, то от порядка их создания будут зависеть все настройки для остальных модулей, сделанных ранее. Они всё время будут меняться благодаря появлению очередного “умного” модуля в программе. Если другой модуль добавит 5 для другого уровня, то ты даже об этом не узнаешь. Сам-то модуль logging расчитывает на то, что это будет делаться в __init__'е всё, как он и сказал в документации своей делать, перед вызовом которого он предварительно сохранит всё состояние модуля, а потом восстановит его обратно после работы.

А ты думал, там просто так про __init__ написано, от нечего делать? Человеку было нечего делать, он про __init__ написал, да? Это вот по твоему мнению: когда ты что-то не понимаешь, то ты вместо того, чтобы свою макушку прочистить лишний раз, перечитать что-то там, уточнить, начинаешь автора дискредитировать, типа автор модуля тупой. А тупой-то ты.

alibek
Но если посмотреть код этого метода (https://github.com/python/cpython/blob/main/Lib/logging/__init__.py#L156), то это не метод класса, а функция в теле модуля
Ты знаешь, это как бы не аргумент. Иметь дело можно только с интерфейсом модуля, это знает любой дурак, а ты не знаешь, потому что ты глупее вот этого вот любого дурака. Ну поздравляю тебя!

Чем это закончится: когда автор поменяет устройство своего кода, не предупредив тебя, такого красивого и умного, твоя программа с этого момента обосрётся прилюдно и всё. А ты будешь что делать - не признавать свои ошибки, про которые ты мне там пишешь дальше, а ты будешь окружающих обвинять, какие они тупые и не понимают, что твоя программа не обосралась, а это они обосрались и валят на твою программу. Это не моё говно! Это мне подложили это говно! Вот твой девиз.

Очень похоже на анекдот вот этот
Анекдот №-311115024

Поручик Ржевский просыпается после пьянки и видит,
что денщик Петруха чистит его обблёванный китель.
Ну поручику, естессно, невздобняк стало - офицер,
и так обблевался. Он и говорит денщику:
- Знаешь, Петруха, вчера на балу встретил своего друга
генерала, а он скотина так нажрался и обблевал мне
весь китель.
- Да, Ваше Благородие, он вам не только китель обблевал,
но ещё и в штаны насрал.

Да, вот так вот ты будешь реагировать, когда тебя ткнут носом в твою говнопрограмму.

alibek
Думаю, что на самом деле причина подобных агрессивных заявлений в другом.
Хорошо, что ты это написал, потому что это всё про тебя написано
alibek
Очевидно, что интернет играет в вашей жизни социальную функцию.
Вероятно, вы рассматриваете данный форум в каком-то смысле как свою территорию.
А там, где есть территория и коллектив, есть и иерархические игры.
Возможно вы думаете, что любая ответная реакция новичка на ваш совет, отличная от благодарности и признательности, является покушением на ваше место в иерархии, на которое, разумеется, нужно дать мгновенный и жесткий отпор.
Поэтому ваши агрессивные заявления про “бред” на самом деле не про корректность (или некорректность) программного кода, а автоматическая реакция с попыткой заранее обесценить любые аргументы соперника, объявив их несущественными и/или ложными.
Реакция поспешная и ошибочная, но признать ошибку вы уже не можете, ведь это публичное место и вдруг другие участники форума подумают, что Акела промахнулся.
Отсюда и пустая болтовня и софистика, чтобы отвлечь от своей ошибки и не допустить падения авторитета.
Только у тебя не социальная функция, это ты немножко подменил, а это по-другому устроено. Ты чему-то там подучился, совсем немного (может, тебя турнули откуда-то, где ты там сидел, присосавшись плотненько, поэтому-то и не развивался вообще, а зачем? на покушать и так дают), и тут ты решил делать так. А вот теперь я сделаю такой финт ушами: создам себе рекламу и буду её везде постить, какой я замечательный, какой я нужный и так далее. Может, кто-то не разберётся и возьмёт меня к себе, чтобы я снова мог сидеть и нихера не делать, как обычно, по привычке. А как же их найти, вот этих дурачков? Хм… да надо зайти просто на какой-нибудь форум, куда ходят всякие шлюшки из этих hh, avito и прочих шараг и ищут, рыщут в поисках специалистов, которых так не хватает вокруг, и там начать продвигать себя, авось клюнут. А раз так, то они же не разберутся, что я полный дебил и ничего не знаю, а потому и поведутся на меня, читая мои письмена и коды великие, которые я будут обильно приправлять своими мнениями тупорылыми и спорами разного рода желательно с кем-нибудь покрупнее (замахнулся бы на создателя модуля logging, но слишком палевно это, могут просто понять, что я дурак обычный, надо осторожнее действовать - назалупаться, например, на какого-нибудь местного авторитета, гуру или кого-нибудь подобного). Сказано - сделано. Главное, надо уверенно себя вести, утверждать, что я мастер этого дела, говорить, что мой код везде всегда правильный, даже если это полная ахинея. Ну вот такая вот стратегия, мне вот кажется она хорошей, я же её САМ придумал, я же умнее всех и никто об этом не догадается даже, все же дураки, а я один умный, а сомневаться в собственной гениальности - это себя не уважать, это моё и-зо-бре-те-ни-е! никто кроме меня никогда так не делал и не приходил на форумы.

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

Ну и вот. Так ты припёрся сюда. Но тут тебя быстренько разнесли.

alibek
Отсюда и пустая болтовня и софистика, чтобы отвлечь от своей ошибки и не допустить падения авторитета.
Какого авторитета? Я тут сижу больше десяти лет. Ты думаешь, сюда никто не приходил и не выяснял про меня ничего? Что я знаю и чего я не знаю? Да тут всё выяснено и перевыяснено десять раз уже. Меня эти вещи вообще не волнуют. Я всему учусь не для того, чтобы кому-то там нравиться, особенно всяким шлюшкам со всяких рабочих платформ, ценность которых не больше чем у сопли под носом, потому что они ничего не умеют делать в жизни и просто сидят и стараются на айтишниках подзаработать себе на жизнь их беспонтовую, на что - на трусы, на булочки. Это все их интересы, они ничем не занимаются, они ничего не развивают, они ничего не изучают. Им это не надо.

А ты хочешь понравиться вот им, использовать форум, а потом сдрыснуть отсюда при первой же возможности, как это делали сотни человек до тебя. Они все такие смазливые, хорошие, дружные, но как только выясняется, что тут денег нет и не будет (кто тут деньги будет искать, да? казалось бы, это же очевидно), так они точно так же, спокойненько собирают свои манатки и тихо-тихо уходят отсюда, даже ни с кем не попрощавшись из своих “друзей” (которые были им не друзьями, а просто так, трамваями, чтобы просто дальше куда-то там проехать на них до следующей остановки, где сытно и вкусно). И тут ты видишь, что вчера учившийся всему и всё познающий со всем большим и огромным интересом ученичок раз и пропал куда-то. Понимаешь? Вот так это работает. Ну что сказать, шлюшкам - шлюшково. Пускай они со своими шлюшками и сидят и друг на друге зарабатывают. А мы будем программированием заниматься, питоном. Понял? Потому что питон выживет, а они все сдохнут.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB