Действительно ли возможно изменить реализацию метода экземпляра, не изменяя все другие экземпляры того же класса?

Я просто собираюсь запуститься с подсказки от меня :)

Использование os.path.dirname () в settings.py для предотвращения hardcoded dirnames.

не Делают hardcode пути в Вашем settings.py, если Вы хотите выполнить свой проект в различных местоположениях. Используйте следующий код в settings.py, если Ваши шаблоны и статические файлы расположены в каталоге проекта Django:

# settings.py
import os
PROJECT_DIR = os.path.dirname(__file__)
...
STATIC_DOC_ROOT = os.path.join(PROJECT_DIR, "static")
...
TEMPLATE_DIRS = (
    os.path.join(PROJECT_DIR, "templates"),
)

Кредиты: Я получил эту подсказку от скринкаста' Django С нуля '.

20
задан S.Lott 2 November 2009 в 01:37
поделиться

5 ответов

Все, что вы хотели знать об Атрибутах и ​​методах Python .

Да, это косвенный ответ, но он демонстрирует ряд методов и объясняет некоторые из более сложные детали и «магия».

Для «более прямого» ответа рассмотрим новый модуль python . В частности, посмотрите на функцию instancemethod, которая позволяет «привязать» метод к экземпляру - в данном случае это позволит вам использовать «self» в методе.

import new
class Z(object):
  pass
z = Z() 
def method(self):
  return self
z.q = new.instancemethod(method, z, None)
z is z.q()  # true
24
ответ дан 29 November 2019 в 22:50
поделиться

Если вы привязываетесь к экземпляру, вы не должны включать аргумент self:

>>> class Foo(object):
...     pass
... 
>>> def donothing():
...     pass
... 
>>> f = Foo()
>>> f.x = donothing
>>> f.x()
>>> 

Вам действительно нужен аргумент self, если вы привязываетесь к классу:

>>> def class_donothing(self):
...     pass
... 
>>> foo.y = class_donothing
>>> f.y()
>>> 
5
ответ дан 29 November 2019 в 22:50
поделиться

Ваш пример запутан и сложен, и я не совсем понимаю, какое отношение он имеет к вашему вопросу. Не стесняйтесь уточнить, если хотите.

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

class Foo(object):
    def bar(self):
        print('bar')

def baz():
    print('baz')

В переводчике ...

>>> f = Foo()
>>> f.bar()
bar
>>> f.bar = baz
>>> f.bar()
baz
>>> g = Foo()
>>> g.bar()
bar
>>> f.bar()
baz
0
ответ дан 29 November 2019 в 22:50
поделиться

Если вам когда-нибудь понадобится сделать это для специального метода (который для класса нового стиля - это то, что вы всегда должны использовать, и единственный в Python 3 - ищется в классе, а не в экземпляре), вы можете просто создать класс для каждого экземпляра, например ...:

self.foo = Foo()
meths = {'__str__': lambda self: 'peekaboo!'}
self.foo.__class__ = type('yFoo', (Foo,), meths)

Изменить : Меня попросили разъяснить преимущества этот подход к new.instancemethod ...:

>>> class X(object): 
...   def __str__(self): return 'baah'
... 
>>> x=X()
>>> y=X()
>>> print x, y
baah baah
>>> x.__str__ = new.instancemethod(lambda self: 'boo!', x)
>>> print x, y
baah baah

Как видите, метод new.instance в данном случае совершенно бесполезен. OTOH ...:

>>> x.__class__=type('X',(X,),{'__str__':lambda self:'boo!'})
>>> print x, y
boo! baah

... назначение нового класса отлично подходит как для этого случая, так и для любого другого. Кстати, как я надеюсь, понятно, как только вы сделаете это с данным экземпляром, вы сможете позже добавить больше методов и других атрибутов класса к его x .__ class __ и по сути повлиять только на этот экземпляр!

8
ответ дан 29 November 2019 в 22:50
поделиться

Не делайте этого.

Изменение методов одного экземпляра - это просто неправильно.

Вот правила объектно-ориентированного дизайна.

  1. Избегайте магии.

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

Это означает, что каждый раз, когда вы думаете, что вам нужно что-то волшебное, вы должен был написать «оболочку» или фасад вокруг объекта, чтобы добавить необходимые вам функции.

Просто напишите оболочку.

0
ответ дан 29 November 2019 в 22:50
поделиться
Другие вопросы по тегам:

Похожие вопросы: