I wish to modify the method of a class by changing its behaviour. Please note that I do NOT wish to rewrite another method altogether as it is complex and involves many variables and interacts with other methods. Here is an example of what I'm trying to do:
import types
class example_class(object):
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
self.pi = 3.14
def example_method(self):
print(self.a * self.b * self.c * self.pi)
#Create an instance of the object and call the method.
my_example = example_class(3, 5, 7)
my_example.example_method()
#Now I wish to change the "example_method" to add instead of multiply.
def different_method(self, a, b, c):
print(self.a + self.b + self.c + self.pi)
my_example.example_method() = types.MethodType(different_method(10,20,30), my_example)
I tried using types.MethodType but the above does not work. Note that I am trying to replace the example.method() with different.method(). I would like to give the method different values to calculate as well.
EDIT:
Thank you to all who answered my question! You have clarified it for me and now I can monkeypatch my classes! However, I should have clarified further. I wished to modify my method to include yet another variable. So my different_method should be like this:
#Now I wish to change the "example_method" to add instead of multiply.
def different_method(self, a, b, c, extra_variable):
print(self.a + self.b + self.c + extra_variable + self.pi)
I am having difficulty adding the extra variable-if you could provide some guidance on that, I’d be very grateful!
You're mixing up function objects, and the values returned by calls to those functions.
First, on the left side of the =, you have this:
my_example.example_method()
So you're not trying to replace the example_method attribute of my_example, you're trying to assign to whatever it returns (here, None). That makes no sense.
Then, on the right side, you're trying to build a method, not out of different_method, but out of the result of calling different_method(10,20,30). This also makes no sense.
What you want is:
my_example.example_method = types.MethodType(different_method, my_example)
Now you can call it the same as any other method:
my_example.example_method(10, 20, 30)
But, while we're at it, your different_method doesn't make much sense either. It takes parameters a, b, c, but completely ignores them, and instead just adds self.a + self.b + self.c. While this isn't illegal, it's kind of silly—and it means that the new method doesn't have the same signature as the one you were replacing, which is bound to cause confusion. So what you probably want is:
def different_method(self):
print(self.a + self.b + self.c + self.pi)
my_example.example_method = types.MethodType(different_method, my_example)
my_example.example_method()
If you want to add different values, you'd create a new example object, just as you would when you want to multiply different values:
my_other_example = example_class(10, 20, 30)
my_other_example.example_method = types.MethodType(different_method, my_other_example)
my_other_example.example_method()
If you plan to do a lot of this monkeypatching, you may want to write a function to patch example objects:
def patch_example(example, different_method):
example.example_method = types.MethodType(different_method, example)
… so you can do this:
my_third_example = example_class(1, 2.5, 0+1j)
patch_example(my_third_example)
my_third_example.example_method()
(However, if you really do need to do this multiple times, you probably wanted to create a subclass, or some other higher-level abstraction.)
# first you replace the method
my_example.example_method = types.MethodType(different_method, my_example)
# then you call it
my_example.example_method(10,20,30)
Related
The problem in code:
class Object:
def __init__(self, x, y):
self.a = some_logic(x)
self.b = some_logic(y)
#classmethod
def produce_object(cls, x, y, additional_knowledge) -> 'Object':
a = some_different_logic(x, additional_knowledge)
b = some_different_logic(y, additional_knowledge)
# now how to initialize Object?
# bad ( I dont want to call some_logic):
o = Object(x, y)
o.a = x
o.b = y
return o
I want to create a new instance, that creates it in another way than the constructor does. For this alternative way I would maybe use some additional knowledge that allows me to call produce_object (which spares me a lot of expensive calculations located in the constructor).
In Java I would place the a and b instance variables outside the constructor in the body of the class.
If I do this in python, they are treated as static members.
Do i have to do something like this ?:
class Object:
def __init__(self):
self.a = None
self.b = None
def former_constructor(self, x, y):
self.a = some_logic(x)
self.b = some_logic(y)
def produce_object(self, x, y):
self.a = some_different_logic(x)
self.b = some_different_logic(y)
My best guess (since you cant have multiple constructors, right?) that one would write a very generic constructor. This of course leads to complicated code in the real world (imagine you have 3 ways to calculate your stuff. One takes arguments of type A and B, second C and D, third E and F. But you always have to provide everything (with potentially four Nones).
Any comment on this is very appreciatied. Thanks for you help.
The #classmethod approach can be modified to provide an alternative
constructor which does not invoke the default constructor (init).
Instead, an instance is created using new.
According to #Andrzej Pronobis
I was wondering if all self. has to be defined in __init__, for example, i have this code right here:
class Colour:
def __init__(self, r, g, b):
self._red = r
self._green = g
self._blue = b
self._rgb = (self._red, self._green, self._blue)
def luminosity(self):
self._luminosity = 0.5 * ((max(self._red, self._green, self._blue))/255)+((min(self._red, self._green, self._blue))/255)
return self._luminosity
Am i right to define self.luminosity in the function def luminosity(self) or should i define it in __init__?
In this case, you don't need to define it, because it's only set and then returned when you could directly return the calculated value from your method!
Additionally, you can simplify the calculation a little, though I am not sure it is really luminosity, as there are a variety of interpretations different to yours
def luminosity(self):
return 0.5 * (
max(self._red, self._green, self._blue) + \
min(self._red, self._green, self._blue)
) / 255
If instead, you were caching the value (which may make sense if you do a more complex calculation or call the luminosity method many times), it would make sense to set it in __init__() and check before calculating (effectively caching the last call)
As #laol suggests, you can also use #property to simplify some of the its use
And finally, you can take advantage of your combined RGB for the calculation
class Colour():
def __init__(self, r, g, b):
self._red = r
self._green = g
self._blue = b
self._luminosity = None
#property
def rgb(self):
return (self._red, self._green, self._blue)
#property
def luminosity(self):
if self._luminosity is None:
self._luminosity = 0.5 * (max(self.rgb) + min(self.rgb)) / 255
return self._luminosity
c = Colour(128,100,100)
print(c.luminosity)
0.44705882352941173
Extending this even further, setting new values for the color components can set the cached value back to None, triggering re-calculation on the next call (rather than immediately, saving some calculation if many changes are made before the value is wanted), but this is left as an exercise to the reader
I suggest to define it as a property:
#property
def luminosity(self):
return 0.5 * ((max(self._red, self._green, self._blue))/255)+((min(self._red, self._green, self._blue))/255)
By this you can directly return it from any Colour c by
c.luminosity
No, instance variables do not need to be defined in __init__. Instance variables are completely dynamic and can be added any time either in a method or outside of the object (see note). However, if you don't define them, you have created an object access protocol that needs to be managed. Suppose another method is added:
def half_luminosity(self):
return self._luminosity/2
It is an error to call it before luminosity. This code will raise AttributeError if its called at the wrong time. You could assign self._luminosity = None in __init__ and check it
def half_luminosity(self):
if self._luminosity is None:
raise ValueError("Attempt to use luminosity before set")
but that's not much different than
def half_luminosity(self):
if not hasattr(self, '_luminosity'):
raise ValueError("Attempt to use luminosity before set")
If you have a class that is setup in more than one step, either way will do. PEP8 favors the first because its easier for a futurer reader to see what's going on.
NOTE: Classes that use __slots__ or one of the getattr methods can change the rules as can C extensions.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 8 years ago.
Improve this question
I have a function compute_params() which computes many variables that I want to use in another function, say main_func(). For the moment, my code is similar to:
def compute_params(i):
a = i/2
b = a + 2.
c = 2*a/b - 1.
d = a + b + c
e = ((a + 1.)**2 - d)/c
# ...and so on with more complex computations and more variables.
return a, b, c, d, e
def main_func(imax):
for i in range(imax):
a, b, c, d, e = compute_params(i)
# Do something with a, b, c, ...
My questions are:
Considering speed issues, is it a problem to return and get 5, 10 variables (or even more in my real life function)?
If the answer to the first question is yes, how to simply do that with a dictionary or something similar, taking into account that I need to keep the real variables names in main_func() (to put them in big equations)?
NB: just to understand why I want to do that, my function compute_params() is used at different places in my code, that's why its content is not directly included in main_func().
Edit to answer several suggestions I have had: I would like to avoid classes or dictionaries because (1) the only thing my variables have in common is being useful in the same equation, thus there is no logical reason for grouping them in an object and, above all (2) since these coefficients appear hundreds of times in complex equations that already are painful to read, I want to avoid things like params.a + params.b/params.c where I currently and simply write a + b/c.
By itself there isn't a speed issue with this. If this code is inside a tight loop, the system runs too slowly for your needs, you have used a profiler and found out that the problem is here, then there might be. It's not at all the first place I would look for speed improvements.
That said: this is unreadable code. You need better variable names, and passing along a large number of variables without more structure than that is a sign of bad code. "compute_params" is also pretty meaningless by itself; what kind of params?
Don't these variables mean something? Can't they be grouped together into one or a small number of classes?
I think you'll find that if you can group some of them together into a well named class, several of the computations you want to do will turn out to fit naturally as methods of that class. But at least, you'd be able to just hand around the class instance instead of an unwieldy list of variables that you have to repeat everywhere.
If you don't like to pass around many variables, you could try to work with a namedtuple. Then you only have to pass around that namedtuple and can still address the variables nicely without unpacking a list:
from collections import namedtuple
variables = namedtuple('variables', ['a', 'b', 'c', 'd', 'e'])
var = variables(1,2,3,4,5)
var.a # 1
var.b # 5
Given the way your parameters are calculated, one option would be a simple class:
class Params(object):
def __init__(self, i):
self.a = i / 2.0
self.b = self.a + 2
self.c = (2 * (self.a / self.b)) - 1.
self.d = self.a + self.b + self.c
self.e = (((self.a + 1) ** 2) - self.d) / self.c
You can then pass around a single instance of this class:
def main_func(imax):
for i in range(imax):
params = Params(i)
# use e.g. params.a in an equation
Alternatively, using a dictionary could look something like:
def create_params(i):
params = {'a': i / 2.0}
params['b'] = params['a'] + 2
params['c'] = (2 * (params['a'] / params['b'])) - 1
params['d'] = params['a'] + params['b'] + params['c']
params['e'] = (((params['a'] + 1) ** 2) - params['d']) / params['c']
return params
This can then be accessed easily by key:
def main_func(imax):
for i in range(imax):
params = create_params(i)
# use e.g. params['a'] in an equation
or, if you have a function that takes the parameters (or some subset), you can unpack the dictionary straight into it:
def func(a, d, **kwargs): # kwargs mops up unused parameters
# does stuff with a and d
return result
result = func(**params)
Are you (kind of) asking for macros ?
You might try karnickel.
That is one of the reasons people invented the object-oriented programming, where same variables can be related to a bunch of functions.
I have started learning python classes some time ago, and there is something that I do not understand when it comes to usage of self.variables inside of a class. I googled, but couldn't find the answer. I am not a programmer, just a python hobbyist.
Here is an example of a simple class, with two ways of defining it:
1)first way:
class Testclass:
def __init__(self, a,b,c):
self.a = a
self.b = b
self.c = c
def firstMethod(self):
self.d = self.a + 1
self.e = self.b + 2
def secondMethod(self):
self.f = self.c + 3
def addMethod(self):
return self.d + self.e + self.f
myclass = Testclass(10,20,30)
myclass.firstMethod()
myclass.secondMethod()
addition = myclass.addMethod()
2)second way:
class Testclass:
def __init__(self, a,b,c):
self.a = a
self.b = b
self.c = c
def firstMethod(self):
d = self.a + 1
e = self.b + 2
return d,e
def secondMethod(self):
f = self.c + 3
return f
def addMethod(self, d, e, f):
return d+e+f
myclass = Testclass(10,20,30)
d, e = myclass.firstMethod()
f= myclass.secondMethod()
addition = myclass.addMethod(d,e,f)
What confuses me is which of these two is valid?
Is it better to always define the variables inside the methods (the variables we expect to use later) as self.variables (which would make them global inside of class) and then just call them inside some other method of that class (that would be the 1st way in upper code)?
Or is it better not to define variables inside methods as self.variables, but simply as regular variables, then return at the end of the method. And then "reimport" them back into some other method as its arguments (that would be 2nd way in upper code)?
EDIT: just to make it clear, I do not want to define the self.d, self.e, self.f or d,e,f variables under the init method. I want to define them at some other methods like showed in the upper code.
Sorry for not mentioning that.
Both are valid approaches. Which one is right completely depends on the situation.
E.g.
Where you are 'really' getting the values of a, b, c from
Do you want/need to use them multiple times
Do you want/need to use them within other methods of the class
What does the class represent
Are a b and c really 'fixed' attributes of the class, or do they depend on external factors?
In the example you give in the comment below:
Let's say that a,b,c depend on some outer variables (for example a = d+10, b = e+20, c = f+30, where d,e,f are supplied when instantiating a class: myclass = Testclass("hello",d,e,f)). Yes, let's say I want to use a,b,c (or self.a,self.b,self.c) variables within other methods of the class too.
So in that case, the 'right' approach depends mainly on whether you expect a, b, c to change during the life of the class instance. For example, if you have a class where hte attributes (a,b,c) will never or rarely change, but you use the derived attribures (d,e,f) heavily, then it makes sense to calculate them once and store them. Here's an example:
class Tiger(object):
def __init__(self, num_stripes):
self.num_stripes = num_stripes
self.num_black_stripes = self.get_black_stripes()
self.num_orange_stripes = self.get_orange_stripes()
def get_black_stripes(self):
return self.num_stripes / 2
def get_orange_stripes(self):
return self.num_stripes / 2
big_tiger = Tiger(num_stripes=200)
little_tiger = Tiger(num_stripes=30)
# Now we can do logic without having to keep re-calculating values
if big_tiger.num_black_stripes > little_tiger.num_orange_stripes:
print "Big tiger has more black stripes than little tiger has orange"
This works well because each individual tiger has a fixed number of stripes. If we change the example to use a class for which instances will change often, then out approach changes too:
class BankAccount(object):
def __init__(self, customer_name, balance):
self.customer_name = customer_name
self.balance = balance
def get_interest(self):
return self.balance / 100
my_savings = BankAccount("Tom", 500)
print "I would get %d interest now" % my_savings.get_interest()
# Deposit some money
my_savings.balance += 100
print "I added more money, my interest changed to %d" % my_savings.get_interest()
So in this (somewhat contrived) example, a bank account balance changes frequently - therefore there is no value in storing interest in a self.interest variable - every time balance changes, the interest amount will change too. Therefore it makes sense to calculate it every time we need to use it.
There are a number of more complex approaches you can take to get some benefit from both of these. For example, you can make your program 'know' that interest is linked to balance and then it will temporarily remember the interest value until the balance changes (this is a form of caching - we use more memory but save some CPU/computation).
Unrelated to original question
A note about how you declare your classes. If you're using Python 2, it's good practice to make your own classes inherit from python's built in object class:
class Testclass(object):
def __init__(self, printHello):
Ref NewClassVsClassicClass - Python Wiki:
Python 3 uses there new-style classes by default, so you don't need to explicitly inherit from object if using py3.
EDITED:
If you want to preserve the values inside the object after perform addMethod, for exmaple, if you want call addMethod again. then use the first way. If you just want to use some internal values of the class to perform the addMethod, use the second way.
You really can't draw any conclusions on this sort of question in the absence of a concrete and meaningful example, because it's going to depend on the facts and circumstances of what you're trying to do.
That being said, in your first example, firstMethod() and secondMethod() are just superfluous. They serve no purpose at all other than to compute values that addMethod() uses. Worse, to make addMethod() function, the user has to first make two inexplicable and apparently unrelated calls to firstMethod() and secondMethod(), which is unquestionably bad design. If those two methods actually did something meaningful it might make sense (but probably doesn't) but in the absence of a real example it's just bad.
You could replace the first example by:
class Testclass:
def __init__(self, a,b,c):
self.a = a
self.b = b
self.c = c
def addMethod(self):
return self.a + self.b + self.c + 6
myclass = Testclass(10,20,30)
addition = myclass.addMethod()
The second example is similar, except firstMethod() and secondMethod() actually do something, since they return values. If there was some reason you'd want these values separately for some reason other than passing them to addMethod(), then again, it might make sense. If there wasn't, then again you could define addMethod() as I just did, and dispense with those two additional functions altogether, and there wouldn't be any difference between the two examples.
But this is all very unsatisfactory in the absence of a concrete example. Right now all we can really say is that it's a slightly silly class.
In general, objects in the OOP sense are conglomerates of data (instance variables) and behavior (methods). If a method doesn't access instance variables - or doesn't need to - then it generally should be a standalone function, and not be in a class at all. Once in a while it will make sense to have a class or static method that doesn't access instance variables, but in general you should err towards preferring standalone functions.
I have a data structure which I'd like to print out in a form that is both human- and machine-readable. Specifically, I want to print it as a call to the constructor which would rebuild the same object if parsed as a Python expression.
The data structure can be inconsistent. (It won't be used in this inconsistent state unless the program is buggy.) If it is inconsistent, I would like to print it out as a call which builds a consistent object (I have a well-defined policy for resolving the inconsistency). However, I use prettyprinting heavily in debugging, so I would like to have some way of revealing the inconsistency. Thus for an inconsistent object, Python should see an expression to construct a consistent object but a human should see the inconsistency.
Here's a silly example. The Sum class's sum field should be the sum of a and b. If it isn't, sum is assumed to be wrong — but I want to see the wrong value of sum in the printout.
class Sum:
def __init__(self, a, b):
self.a = a
self.b = b
self.update()
def update(self):
self.sum = self.a + self.b
def __str__(self):
return 'Sum(%s, %s)%s' % \
(str(self.a), str(self.b),
'' if self.sum == self.a + self.b else ' # sum=' + str(self.sum))
Demo:
>>> x = Sum(1, 2)
>>> str(x)
'Sum(1, 2)'
>>> x.a = 2
>>> str(x)
'Sum(2, 2) # sum=3'
This is not good because Sum(2, 2) # sum=3 cannot be parsed as part of a larger expression. I don't want to rely on line breaks, either, as the printout could be copied around as text with line wrapping.
I could add an optional parameter to the constructor to build an inconsistent object, but it would be messy. Objects are never supposed to be created in an inconsistent state.
How else can I print something out that Python will parse but ignore?