Модификация класса Python - PullRequest
2 голосов
/ 30 января 2010

Я хотел бы изменить все классы в Python. Например, str, int и другие, такие как Person (объект).

Я бы хотел добавить к ним атрибут и изменить способ его работы.

Какой подход лучше для этого? Метаклассы

Ответы [ 4 ]

3 голосов
/ 30 января 2010

Хотя вы можете сделать это для классов, определенных в коде Python (он не будет работать для встроенных) путем переназначения их атрибутов, на самом деле не делайте этого. Просто создайте подкласс и используйте подкласс, или напишите функции, которые принимают экземпляр класса в качестве аргумента вместо добавления ваших собственных методов. Выполнение того, что вам нужно, приводит к неловкому, хрупкому коду, особенно если вы в конечном итоге используете несколько библиотек одновременно, которые пытаются сделать это для одних и тех же классов.

Есть ли реальная проблема, которую вы пытаетесь решить таким образом?

1 голос
/ 30 января 2010

Встроенные классы нельзя изменить, но вы можете «скрыть» встроенный класс (или любой другой, разумеется) под тем же именем.

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

def changedclass(cls):
  def __init__(self, *a, **k):
    cls.__init__(self, *a, **k)
    self.murf = 45
  return type(cls.__name__, (cls,), {'foobar': 23, '__init__': __init__})

def changemany(changed, classes_by_module):
  for module, classnames in classes_by_module.iteritems():
    for name in classnames:
      cls = getattr(module, name)
      subcls = changed(cls)
      setattr(module, name, subcls)

import __builtin__
import mymod
changemany(changedclass, {__builtin__: ('int', 'str'), mymod: ('Person',)})

Обратите внимание, что голые литералы, такие как 'ciao' и 23, по-прежнему будут принадлежать классам real - изменить это невозможно; вам нужно использовать str('ciao') и int(23), чтобы использовать "поддельные" классы.

0 голосов
/ 30 января 2010

подкласс:


class int(int):
  def foo(self):
   print "foo"

int(2).foo()
0 голосов
/ 30 января 2010

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

...