How to add new method to Django class from other modules? [duplicate] - python

This question already has answers here:
Adding a method to an existing object instance in Python
(19 answers)
Closed 6 years ago.
I have a Django model say:
class MyOperation(models.Model):
name = models.CharField(max_length=100)
def my_method(self):
pass
I want to be able to add, from a different Django app, a new method to this class.
I tried to do this from a different app module called custom.py:
from operations.models import MyOperation
def op_custom(test):
print "testing custom methods"
MyOperation.op_custom = op_custom
However this does not seems to work, in runtime the method does not exists.
Is this the way to modify the definition of a class from a different django application? Is there a better way to do it?
Thanks

The Right Way™ to do this is via a mixin:
class MyMixIn(object):
def op_custom(self):
print("foo")
class MyOperation(models.Model, MyMixIn):
def op_normal(self):
print("bar")
This has several advantages over monkey-patching in another method:
The mixin is in the class' method resolution order, so introspection works perfectly.
It is guaranteed to be defined on every instance of the class regardless of where it is instantiated since the class itself inherits from the mixin. Otherwise, you may end up with instances from before the monkey patch is applied where this method isn't there.
It provides an obvious place to add such methods in the future.

Related

Can you selectively inherit methods in Python? [duplicate]

This question already has answers here:
Is it possible to do partial inheritance with Python?
(4 answers)
Closed 8 months ago.
I have a parent class with a lot of methods. I want some of them inherited in all of the child classes. Some of the methods I only want in certain classes. Can I somehow select which methods to inherit. I know I could override them in the child class, but I would prefer a positive approach of adding what you want instead of overriding the ones you don't want.
I am using the backtrader library.
class BaseStrategy(bt.Strategy):
def notify_cashvalue(self, cash, value):
if value < self.starting_cash * self.terminate_threshold:
self.log(f'Stopping strategy at due drop below {self.terminate_threshold * 100}% of initial cash.')
self.cerebro.runstop()
This is the class I want inherit from. As you see parent class is a child class to the library base, but this class implements empty methods.
Methods like notify_cashvalue are always called when this class is used. In my example notify_cashvalue has some attributes that will not be defined in all the child classes, so there would an error as notify_cashvalue is allways called, as are several other functions, which I want to selectively inherit.
I found here Is it possible to do partial inheritance with Python? that you can select the methods you want in this way:
class Class0():
def hello():
return "Hello"
def bye():
pass
def nice():
pass
class Class1():
Hello = Class0.hello

Can python class reference nonexistent variable and method? [duplicate]

This question already has answers here:
What is a mixin and why is it useful?
(18 answers)
Closed 2 years ago.
class SoftDeleteMixin(object):
deleted_at = Column(DateTime)
deleted = Column(types.SoftDeleteInteger, default=0)
def soft_delete(self, session):
"""Mark this object as deleted."""
self.deleted = self.id
self.deleted_at = timeutils.utcnow()
self.save(session=session)
In class SoftDeleteMixin method soft_delete, it references nonexistent self.id and self.save. Why can it do that in python?
Note: the focus is the class can reference nonexistent variable and method, not that it is a Mixin class.
If you instantiate a SoftDeleteMixin class and call the soft_delete method, you'll get an AttributeError.
If as you said in the comment those attributes are instantiated somewhere else, even in a child class, and you call soft_delete on a child class instance, it works because the attribute is there at the time the method is called.
To explain it in a simple way, python is an interpreted language, and except for syntax it does not perform too much checks on the whole file when executing the code, until that actual line is actually executed.
So yes, you could think it's a bad design but it is not, it's an accepted practice (see this question for more details) and it is allowed by the laguage. You can define methods which reference attributes not defined in a __init__ method or as class attributes or whatever. The important thing is that the istance has the attribute when the method is executed. It does not matter where or when the attribute is actually defined.
The word "mixin" in the class name means that this class is intended to be inherited by a class that already declares id and save(). If you try to use it by itself, it will cause errors.

Is it ok to use children method in abstract class? pep8 says instance has no member [duplicate]

This question already has answers here:
Is it possible to make abstract classes?
(14 answers)
Closed 5 years ago.
I use pep8 in visual studio code and I just tried to write some abstract classes.
The problem is I get the error [pylint] E1101:Instance of 'MyAbstract' has no 'child_method' member because pep8 does not realise that the method is well defined, but in the child classes.
To illustrate my problem here is a code snippet that is reducted to the minimum for clarity:
class MyAbstract:
def some_method(self):
newinfo = self.child_method()
# use newinfo
class MyChild(MyAbstract):
def child_method(self):
# Do something in a way
class OtherChild(MyAbstract):
def child_method(self):
# Do the same thing in a different way
So my questions are:
Is it ok to write classes like this?
How would you solve the error? (disable error, use another pattern, ...)
Clarification
The MyAbstract class shouldn't be instanciated, and the child classes will inherit the some_method. The idea is to use it on child class instances.
If you want MyAbstract to be an abstract class with abstract method child_method, Python has a way of expressing that in the abc module:
import abc
class MyAbstract(metaclass=abc.ABCMeta):
#abc.abstractmethod
def child_method(self):
pass
def some_method(self):
newinfo = self.child_method()
do_whatever_with(newinfo)
Your linter will no longer complain about the nonexistent method, and as a bonus, Python will detect attempts to instantiate a class with unimplemented abstract methods.

Getting the name of a class from within a class definition [duplicate]

This question already has answers here:
how to get derived class name from base class
(7 answers)
Closed 5 years ago.
So I have my base class:
class Foo():
pass
I'm never going to instantiate this class - I just want it as a custom namespace. One of the things I want from it is its name:
>>> Foo.__name__
'Foo'
But I want to change the interface to this, so that there's no underscores. Getting the name of the class from the class object is going to happen a lot, so it should be cleaner:
class Foo:
def name():
return Foo.__name__
This works great! Oh, except I have the name "Foo" hard coded. I might as well just have it return a string. That's not good enough, because I need to inherit this adjustment:
class Bar(Foo):
pass
>>> Bar.name()
'Foo'
No bueno.
Basically, I need a class function that returns the name of the class, and which will still work when inherited. I can't use self because I'm not making instances. Is there anything which will achieve a similar result? Do functions know about the namespace they are called from? If I really need to use objects I will, but for my purposes that will be uglier than a simple class hierarchy.
EDIT: I do not not believe this question is the same as the one it has been linked with. The solutions provided to the other question - mainly invoking the .__class__ attribute - would not work as an answer to this question because in my example I explicitly avoid instantiating objects. Also, the best answer provided here (using the #classmethod decorator to get the class object as a "self"-esque arg) appears nowhere in the linked alternative. Also, I believe my question to be framed in a clearer and more basic way than its purported duplicate. The same goes for the answer chosen.
Just make it a class method with #classmethod and return the name of the class that's passed in:
class Foo:
#classmethod
def name(cls):
return cls.__name__
class Bar(Foo): pass
This returns the correct name in each case:
>>> Foo.name()
'Foo'
>>> Bar.name()
'Bar'

in python,what is the difference below, and which is better [duplicate]

This question already has answers here:
Difference between #staticmethod and #classmethod
(35 answers)
Closed 9 years ago.
I have written a code like this,and they are all works for me,but what is the difference? which is better?
class Demo1(object):
def __init__(self):
self.attr = self._make_attr()
def _make_attr(self):
#skip...
return attr
class Demo2(object):
def __init__(self):
self.attr = self._make_attr()
#staticmethod
def _make_attr():
#skip...
return attr
If both are working it means that inside make_attr you are not using self.
Making it a regular non-static method only makes sense if the code could logically depend on the instance and only incidentally doesn't depend on it in the current implementation (but for example it could depend on the instance in a class derived from this class).
When it comes to functionality, #staticmethod doesn't really matter. It's value is semantic - you are telling yourself, or other coders, that even though this function belongs to the namespace of the class, it isn't tied to any specific instance. This kind of tagging can be very useful when refactoring the code or when looking for bugs.
In either, attr is a local variable and does not depend on anything in the class. The results are the same. Marking it as static gives you the benefit of knowing this, and being able to access it directly, such as Demo2._make_attr() without having to create and instance of the class.
If you want it to acces the class variable, you would reference it as self.attr. But if you're doing this, then Demo2._make_attr() can no longer be static.

Categories