Как уже упоминалось в комментариях, вы создаете новый атрибут здесь:
inst_a.new_var = 20
перед прочтением его на следующей строке. Вы НЕ назначаете newDummyPrint
где-либо, поэтому очевидно, что механизм разрешения атрибутов не может его найти и в конечном итоге вызывает AtributeError. Тот же самый результат вы получите, если попытаетесь получить доступ к любому другому несуществующему атрибуту, ie inst_a.whatever
.
Обратите внимание, что поскольку в Python все является объектом (включая классы, функции и т. Д.) c), нет никакого реального различия между доступом к атрибуту «data» или методу - все они являются атрибутами (классом или экземпляром), и правила разрешения атрибута одинаковы. В случае методов (или любого другого вызываемого атрибута) операция вызова происходит после того, как атрибут был разрешен.
Для динамического создания нового «метода» у вас есть в основном два решения: создание в виде атрибута класса (который сделает его доступным для всех других экземпляров класса) или в качестве атрибута экземпляра (который будет - очевидно - сделайте его доступным только в этом конкретном экземпляре.
Первое решение настолько простое, насколько это возможно: определите свою функцию и привяжите ее к классу:
# nb: inheriting from `object` for py2 compat
class Foo(object):
def __init__(self, var):
self.var = var
def bar(self, x):
return self.var * x
# testing before:
f = Foo(42)
try:
print(f.bar(2))
except AttribteError as e:
print(e)
# now binds the function to the class:
Foo.bar = bar
# and test it:
print(f.bar(2))
# and it's also available on other instances:
f2 = Foo(6)
print(f2.bar(7))
Создание Метод экземпляра (очень крошечный) немного сложнее - вы должны вручную получить метод из функции и связать этот метод с экземпляром:
def baaz(self):
return "{}.var = {}".format(self, self.var)
# test before:
try:
print(f.baaz())
except AttributeError as e:
print(e)
# now binds the method to the instance
f.baaz = baaz.__get__(f, Foo)
# now `f` has a `baaz` method
print(f.baaz())
# but other Foo instances dont
try:
print(f2.baaz())
except AttributeError as e:
print(e)
Как вы заметили, я говорил о функциях в первом case и методы во втором case. A python "method" - это на самом деле просто тонкая вызываемая оболочка вокруг функции, экземпляра и класса , и предоставляется типом function
через протокол дескриптора - который вызывается автоматически, когда атрибут разрешается в самом классе (=> атрибут класса, реализуемый в дескрипторе r), но не при разрешении по экземпляру. Вот почему во втором случае мы должны вручную вызвать протокол дескриптора.
Также обратите внимание, что существуют ограничения на то, что здесь возможно: во-первых, __magic__
методы (все методы с именем с двумя начальными и двумя последними подчеркиваниями), которые ищутся только для самого класса, поэтому вы не можете определить их для каждого экземпляра. Тогда типы на основе слотов и некоторые встроенные или C -кодированные типы вообще не поддерживают динамические c атрибуты. Эти ограничения в основном существуют для оптимизации производительности.