NoAbL
NoAbL

Reputation: 95

Python 3: Adding function to a already created object

I want to add a function to a class, and it should work for all objects from that class, also if they were created before. BUT I don't know the names of the objects already created.

class Dog(object):
"""This is a simple test"""
i = 1234
def f(self):
    return 'hello world'

If i want to implement a function bark to the class Dog and already created Dogs can "use" this function, how would i do this?

I was searching in the Internet before and found

a = Dog()
a.bark = types.MethodType(...)

But i can't use that, because i don't know the name of the object. Maybe somehow you can find out the names of objects from a class.

Can you help me?

Thanks! NoAbL

Upvotes: 1

Views: 282

Answers (3)

Goodies
Goodies

Reputation: 4681

Python objects don't really work like that. Functions are actually different from instance (or bound) methods. There are a couple things that you COULD do, but I wouldn't necessarily recommend For example:

import types  # needed for assigning it to a method type

class foo:
    def __init__(self, i):
        self.i = i

a = foo(7)
b = foo(3)

def bar(self):
    return self.i

vars = dict(globals())
vars.update(locals())

for var in vars:
    if isinstance(vars[var], foo):
        vars[var].bar = types.MethodType(bar, vars[var])

print(a.bar())  # => 7
print(b.bar())  # => 3

This, however, is obviously a band-aid and doesn't address the real problem. Once you create an instance of a class, it can change only so much. The INSTANCE can change, but it won't affect all instances at once unless you overwrite certain data. For example, I could do foo.i = 100 and then both a.i and b.i would be 100. This doesn't seem to be what you want, however.

Something kinda-sorta close may, but may better highlight the issues of this:

class foo:
    def __init__(self, i):
        self.i = i

a = foo(7)
b = foo(3)

def bar(self):
    return self.i

foo.bar = types.MethodType(bar, a)
print(a.bar())  # => 7
print(b.bar())  # => 7
foo.bar = types.MethodType(bar, b)
print(a.bar())  # => 3
print(b.bar())  # => 3
foo.bar = types.MethodType(bar, foo)
print(a.bar())  # => AttributeError: class foo has no attribute 'i'

Upvotes: 1

Yoav Glazner
Yoav Glazner

Reputation: 8066

To change only the instance method (not the Dog class you can do it like this)

import functools
dog.bark = functools.partial(f, dog)

Upvotes: 1

inspectorG4dget
inspectorG4dget

Reputation: 113915

You're right that a.bark modifies the specific instance of Dog and not the class itself.

If you want to modify the Dog class, then you should find the variable that talks about the class. Luckily, that variable is conveniently named after the name of the class itself (as is the case with any class in python), and can therefore be accessed with the variable name Dog.

So, if you do

Dog.bark = types.MethodType(...)

that'll change the Dog class, making bark available to all instances of Dog (regardless of whether they existed before you made this change)

Upvotes: 3

Related Questions