Say I'm writing a module, MyPyLib, that uses another built-in module. From the built-in module, I import a class, Foo. I then define this function, bar:
def bar(self):
return self
This function is written to be a method of the Foo class and I can make it behave properly with setattr(Foo,'bar', bar). Then Foo.bar() will work as intended. However, anyone who imports MyPyLib can also call bar as its own function. Is there any way to limit this function so that Foo.bar() works, but bar(arg) doesn't?
Your code should not care about incorrect use, that's a problem for the caller. Python is a language for consenting adults; if someone wants to bend the rules and use bar with a different argument, that's their problem, not yours.
If you insist, your only option here is to explicitly test for the type of self:
def bar(self):
assert isinstance(self, Foo)
return self
as there is no way for bar to detect otherwise that it is being called as a bound method or used unbound.
An alternative (and more usual) approach is to derive a new class from class Foo and to define bar explicitly as a method of the new class:
class FooBar(Foo):
def bar(self):
return self
This way the intended usage of bar is much more clear.
Related
I have an Object of the following class which inherates from the algorithm class.
class AP(Algorithm):
def evaluate(self, u):
return self.stuff *2 +u
The Algorithm class has a method called StoppingCritiria.
At some point in the project the object objAP = AP() gets created. Later on I can then actually access it.
And at that point in time I want to override the method StoppingCriteria by some function which calls the old StoppingCriteria.
I tried simply
def new_stopping(self):
return super().StoppingCriteria() and custom(self.u)
objAP.StoppingCriteria = newStoppingCriteria
But that did not work. What did work were two rather inconviniend solutions:
New AP class (not desirable since I possibly need to do that for lots of classes)
class AP_custom(AP):
def StoppingCriteria(self):
return super().StoppingCriteria() and custom(self)
Override the Method but not using super but rather copy pasting the code into the new function and adding my code to that. Not desirable since I want to changes in the original method to be applyed to my new function as well.
See Override a method at instance level for many possible solutions. None of them will really work with super though, since you're simply not defining the replacement function in a class. You can define it slightly differently though for it to work:
class Foo:
def bar(self):
print('bar')
f = Foo()
def _bar(self):
type(self).bar(self) # or Foo.bar(self)
print('baz')
from typing import MethodType
f.bar = MethodType(_bar, f)
f.bar() # outputs bar baz
Since you're replacing the method at the instance level, you don't really need to access the method of the super class, you just want to access the method of the class, which still exists in its original form.
I've read this SO discussion about factory methods, and have an alternate constructor use case.
My class looks like this:
class Foo(object):
def __init__(self, bar):
self.bar = bar
#classmethod
def from_data(cls, datafile):
bar = datafile.read_bar()
# Now I want to process bar in some way
bar = _process_bar(bar)
return cls(bar)
def _process_bar(self, bar)
return bar + 1
My question is, if a #classmethod factory method wants to use a function in its code, should that function (_proces_bar) be:
A #classmethod, which seems a bit weird because you won't ever call it like Foo._process_bar()
A method outside of the class Foo but in the same .py file. I'd go with this, but it seems kind of weird. Will those methods always be available to an instance of Foo, regardless of how it was instantiated? (e.g. what if it's saved to a Pickle then reloaded? Presumably methods outside the class will then not be available!)
A #staticmethod? (see 1. This seems weird)
Something else? (but not this!)
The "right solution" depends on your needs...
If the function (_process_bar) needs an access to class Foo (or the current subclass of...) then you want a classmethod - which should be then called as cls._process_bar(), not Foo._process_bar().
If the function doesn't need an access to the class itself but you still want to be able to override it in subclasses (IOW : you want class-based polymorphism), you want a staticmethod
Else you just want a plain function. Where this function's code lives is irrelevant, and your import problems are othogonal.
Also, you may (or not, depending on your concrete use case) want to allow for more flexiblity using a callback function (possibly with a default), ie:
def process_bar(bar):
return bar + 1
class Foo(object):
#classmethod
def from_data(self, datafile, processor=process_bar):
bar = datafile.read_bar()
bar = processor(bar)
return cls(bar)
My class looks like this:
class A:
def __init__(self):
self.bar = []
...
#property
def foo(self):
return bar
Is there a way to find out inside foo whether a method will be called on its return value? I would like to be able to change the return value of foo depending on whether
a.foo.foobar()
or
a.foo
is called.
You could use a proxy class wrapping self.bar (or just self FWIW) in foo()) and overload the proxy's __getattr__() or __getattribute__ methods (more tricky and can slow down your program quite a bit but well...).
Now the question is: what is your real problem ? There might be better / safer solutions...
for the fun of it...
#!/usr/bin/python
import traceback
def how_was_i_called():
call=traceback.extract_stack(limit=2)[0][3]
print "I was called like this: %s"%call
how_was_i_called()
try:
how_was_i_called().foobar()
except AttributeError:
pass
returns:
I was called like this: how_was_i_called()
I was called like this: how_was_i_called().foobar()
but please do not use hacks like this in real applications...
No, there is not. foo returns, and what happens with the return value after that is an entirely separate issue.
You could do this, for example:
result = a.foo
if some_condition:
result.foobar()
e.g. accessing the foobar method on a.foo is an entirely separate expression that may or may not be executed. This could happen at a much later time too, or in a separate thread, or after serialising the object to disk, then loading it again, etc.
You can hook into attribute access on the returned object, but that'll be too late for your foo property to alter behaviour.
I'd like to change the implementation depending on a constructor argument. Below is an example showing what I mean:
class Device(object):
def __init__(self, simulate):
self.simulate = simulate
def foo(self):
if simulate:
self._simulate_foo()
else:
self._do_foo()
def _do_foo(self):
# do foo
def _simulate_foo(self):
# simulate foo
Now every call to foo() invokes an if clause. To avoid that I could bind the correct method dynamically to foo.
class Device(object):
def __init__(self, simulate):
if simulate:
self.foo = self._simulate_foo
else:
self.foo = self._do_foo()
def _do_foo(self):
# do foo
def _simulate_foo(self):
# simulate foo
Are there any drawbacks why this should not be done or other drawbacks I'm not aware? Is this really faster?(I'm aware that inheritance is another option)
I'd like to suggest the Replace Conditional with Polymorphism refactoring instead, as it solves your problem in a more elegant way than both the current code and the suggested alternative:
class Device(object):
def foo(self):
# do foo
class SimulatedDevice(object):
def foo(self):
# simulate foo
What you are doing is perfectly fine, and you'll find the technique used in plenty of Python frameworks. However, you may want to use timeit to check if this is really faster.
When you access instance.foo, Python will first look for it in the class definition to make sure it's not a data descriptor (such as a property), then look it up in the instance namespace, but this is a very fast lookup since foo is not defined in the class (setting self.foo stores it in the instance __dict__ namespace).
The if statement is almost certainly slower than that double lookup, since the if statement itself needs to look up self.simulate in the same manner, but the difference will be negligible.
I'm teaching myself Python and I see the following in Dive into Python section 5.3:
By convention, the first argument of any Python class method (the reference to the current instance) is called self. This argument fills the role of the reserved word this in C++ or Java, but self is not a reserved word in Python, merely a naming convention. Nonetheless, please don't call it anything but self; this is a very strong convention.
Considering that self is not a Python keyword, I'm guessing that it can sometimes be useful to use something else. Are there any such cases? If not, why is it not a keyword?
No, unless you want to confuse every other programmer that looks at your code after you write it. self is not a keyword because it is an identifier. It could have been a keyword and the fact that it isn't one was a design decision.
As a side observation, note that Pilgrim is committing a common misuse of terms here: a class method is quite a different thing from an instance method, which is what he's talking about here. As wikipedia puts it, "a method is a subroutine that is exclusively associated either with a class (in which case it is called a class method or a static method) or with an object (in which case it is an instance method).". Python's built-ins include a staticmethod type, to make static methods, and a classmethod type, to make class methods, each generally used as a decorator; if you don't use either, a def in a class body makes an instance method. E.g.:
>>> class X(object):
... def noclass(self): print self
... #classmethod
... def withclass(cls): print cls
...
>>> x = X()
>>> x.noclass()
<__main__.X object at 0x698d0>
>>> x.withclass()
<class '__main__.X'>
>>>
As you see, the instance method noclass gets the instance as its argument, but the class method withclass gets the class instead.
So it would be extremely confusing and misleading to use self as the name of the first parameter of a class method: the convention in this case is instead to use cls, as in my example above. While this IS just a convention, there is no real good reason for violating it -- any more than there would be, say, for naming a variable number_of_cats if the purpose of the variable is counting dogs!-)
The only case of this I've seen is when you define a function outside of a class definition, and then assign it to the class, e.g.:
class Foo(object):
def bar(self):
# Do something with 'self'
def baz(inst):
return inst.bar()
Foo.baz = baz
In this case, self is a little strange to use, because the function could be applied to many classes. Most often I've seen inst or cls used instead.
I once had some code like (and I apologize for lack of creativity in the example):
class Animal:
def __init__(self, volume=1):
self.volume = volume
self.description = "Animal"
def Sound(self):
pass
def GetADog(self, newvolume):
class Dog(Animal):
def Sound(this):
return self.description + ": " + ("woof" * this.volume)
return Dog(newvolume)
Then we have output like:
>>> a = Animal(3)
>>> d = a.GetADog(2)
>>> d.Sound()
'Animal: woofwoof'
I wasn't sure if self within the Dog class would shadow self within the Animal class, so I opted to make Dog's reference the word "this" instead. In my opinion and for that particular application, that was more clear to me.
Because it is a convention, not language syntax. There is a Python style guide that people who program in Python follow. This way libraries have a familiar look and feel. Python places a lot of emphasis on readability, and consistency is an important part of this.
I think that the main reason self is used by convention rather than being a Python keyword is because it's simpler to have all methods/functions take arguments the same way rather than having to put together different argument forms for functions, class methods, instance methods, etc.
Note that if you have an actual class method (i.e. one defined using the classmethod decorator), the convention is to use "cls" instead of "self".