How to define method of class outside of class? - python

In C++ we can easily define methods outside of class:
struct X {
int a, b ;
// member function declaration only
int add();
};
// define member function outside its class declaration
int X::add() { return a + b; }
I want to do the same thing (or something like this in python) but I don't know how
I saw some solutions to similar problems but they included creating some new functions like this:
def my_func(self_class, arg):
# do something with arg
return something
class MyClass:
function = my_func
Is it possible to define method outside of class without creating unnecessary functions?

The lambda way
You example can be done with lambda and =:
class X:
pass
X.add = lambda s: s.a + s.b
The def way
The def keyword won't allow you to assign directly to a class, but you can make a function, assign it, and then delete it. While this isn't what you were hoping for, it is likely the best you can do:
class X:
pass
def add(s):
return s.a + s.b
X.add = add
del add

Guess I am not sure what you're trying to avoid unless you have functions you want to use in many classes. In that case I would make a base class and inherit it.
As for your second example, calling an external function means you need to explicitly pass "self" since the instance won't do that for you. Another reason I prefer inheritance.
The example is very basic so I am not sure what you wish to achieve. For example add can be built into the class using an overload of __add__. I do that with classes for Vectors.

Python doesn't allow you to define functions in a namespace for another. You can only assign functions to class after defining them. If you want to avoid manual assignment, you can define a simple decorator to help you:
def methodof(tp):
def setter(func):
setattr(tp, func.__name__, func)
return func
return setter
Test:
>>> class Foo:
... pass
...
>>> #methodof(Foo)
... def hello(self):
... print('hello')
...
>>> Foo().hello()
hello

Related

Reuse docstring from a method in a class in python

So I have a method in a class and I have another separate function (i.e., outside the class) that want to reuse the docstring of that method. I tried something like __doc__ = <Class Name>.<Method Name>.__doc__ under the separate function but that does not work. Thus, is there a way to do so?
__doc__ needs to be assigned as a property of the new function, like this:
class C:
def foo(self):
'docstring'
def bar():
pass
bar.__doc__ = C.foo.__doc__ # NOT __doc__ = ...
assert bar.__doc__ == 'docstring'
Even this is a case, I'd use a manual copy of a docstring. Class or function could be moved around or separated to different projects. Moreso, reading a function below goesn't give me any idea what it's doing.
Please, consult with PEP-8, PEP-257 and PEP-20 for more information why this behavior is discoraged.
def myfunc():
...
myfunc.__doc__ = other_obj.__doc__

Refer to parent's class method without parent's class name

I hope you are doing great. This questions is really about getting rid of the reference to base class.
Basically I want to collect all methods of a child class methods at the class level instead of the instance level, using a parent classmethod. However, I was told that the base class name is really long.
The first piece works but is really annoying because of the long name. Even in the clean version I have to do A.eat everytime.
I promise people won't define another method "eat" in any child like B. Can I actually get rid of the base class reference so that I can use #eat?
class IDontWantToDoThisButNameHasToBeThisLong(object):
a = []
#classmethod
def eat(cls, func):
cls.a.append(func)
class B(IDontWantToDoThisButNameHasToBeThisLong):
#IDontWantToDoThisButNameHasToBeThisLong.eat
def apple( self, x ):
print x
IDontWantToDoThisButNameHasToBeThisLong.eat( lambda x: x+1 )
x = B()
IDontWantToDoThisButNameHasToBeThisLong.a[0](x, 1)
print IDontWantToDoThisButNameHasToBeThisLong.a[1](1)
Clean version:
class A(object):
a = []
#classmethod
def eat(cls, func):
cls.a.append(func)
class B(A):
#A.eat
def apple( self, x ):
print x
A.eat( lambda x: x+1 )
x = B()
A.a[0](x, 1)
print A.a[1](1)
Sincerely,
The class IDontWantToDoThisButNameHasToBeThisLong is really just an object. In python, most thingsa are an object, so we can assign just about anything to a variable, including a class.
What you could do here is something like the following
class IDontWantToDoThisButNameHasToBeThisLong(object):
a = []
#classmethod
def eat(cls, func):
cls.a.append(func)
A = IDontWantToDoThisButNameHasToBeThisLong
class B(A):
#A.eat
def apple( self, x ):
print x
A.eat( lambda x: x+1 )
x = B()
IDontWantToDoThisButNameHasToBeThisLong.a[0](x, 1)
A.a[0](x, 1)
print IDontWantToDoThisButNameHasToBeThisLong.a[1](1)
There's no perfect solution for what you want to do, but there are a few different approaches that might be good enough.
To start with the simplest, you could give your long class a shorter name before using class method in the child classes:
class IDontWantToDoThisButNameHasToBeThisLong(object):
...
A = IDontWantToDoThisButNameHasToBeThisLong
# later code can use A.whatever()
Another option would be to move the decorator out of the class with the long name, so that your later code would refer to it directly as a global, rather than a class method. This would require it to be slightly redesigned (which might break things if you ever intend for there to be multiple different a lists that are accessed through the same decorator called via different classes):
class IDontWantToDoThisButNameHasToBeThisLong(object):
a = []
def eat(func):
IDontWantToDoThisButNameHasToBeThisLong.a.append(func) # only need to use the name once
return func # I suspect you want this too (a decorator should return a callable)
# later code can use #eat as a decorator, without referring to the long class name
A hybrid of those two approaches might be to leave the existing class method definition intact, but to create another global name for the bound method that's easier to access:
eat = IDontWantToDoThisButNameHasToBeThisLong.eat
A final possible approach would be to use fancier programming with metaclasses, or (if you're using Python 3.6) __init_subclass__ or similar, to achieve the goal you have in mind without needing to use a class method as a decorator. I'm not going to include code for that, since the best way to do this probably depends on more details of your design than what you've show in your example.

Dynamic class creation - Python

Here is the scenario:
I have two classes:
class A:
pass:
class B:
pass
Now I want to create a client, in that I need to have a small utility method, which should return my class template/object e.g: class A, class B, as I pass on the class name to that utility e.g get_obj(classA).
Now, is this possible? If then please suggest an approach, as I don't get any correct answer as of now in web.
Hope I am making sense.
Here is a possible implementation. All the code is contained in a single '.py' file
class A:
pass
class B:
pass
# map class name to class
_classes = {
A.__name__: A,
B.__name__: B,
}
def get_obj(cname):
return _classes[cname]()
# test the function
if __name__ == '__main__':
print get_obj('A')
It will produce the following output
<__main__.A instance at 0x1026ea950>
Standard library function namedtuple creates and returns a class. Internally it uses exec. It may be an inspiration for what you need.
Source code: https://github.com/python/cpython/blob/master/Lib/collections/init.py#L356
globals() returns a dictionary containing all symbols defined in the global scope of the module (including classes A and B):
a_and_b_module.py
class A: pass
class B: pass
def get_cls(cls_name):
return globals()[cls_name]
If you are looking for simplicity
If the code that will call this function is inside the module, then you can eliminate the function altogether and use globals()[cls_name] directly.
If the code that will call this function is outside the module, then you could use getattr function:
a_and_b_module.py
class A: pass
class B: pass
another_file.py
import a_and_b_module
cls_name = 'A'
chosen_cls = getattr(a_and_b_module, cls_name)
If you are looking for complete control
The problem with the approach above is that it could return anything defined in a_and_b_module.py, not restricting itself to A and B. If you want to make sure only A and B can be returned:
class A: pass
class B: pass
allowed_classes = ('A', 'B')
def get_cls(cls_name):
assert cls_name in allowed_classes
return globals()[cls_name]
Note: you might also be interested in the concept of factory.

Calling a static method inside of a Python class definition

I have a class definition which defines a static method. I have a field which I would like to initialize with the static method. My default thinking led me to this:
class SomeConcreteClass(object):
some_data = SomeConcreteClass.create_default_data()
#staticmethod
def create_default_data():
return 'Foo'
The problem is that when I run this, I get a NameError: name 'SomeConcreteClass' is not defined. It makes sense as the SomeConcreteClass is just being built. Does this mean I cannot use static init functions? Is there an alternate way which is recommended to handle such a situation?
The appropriate place for create_default_data would be outside the class entirely. Then your problems go away:
def create_default_data():
return 'Foo'
class SomeConcreteClass(object):
some_data = create_default_data()
If you really do want it as a static method inside the class that's alright too:
def _create_default_data():
return 'Foo'
class SomeConcreteClass(object):
some_data = _create_default_data()
create_default_data = staticmethod(_create_default_data)
but static methods aren't often used in Python because there's no need to put a function inside a class unless it operates on the class in some way.
If some_data is exactly the output of create_default_data (and assuming the latter is deterministic in the context of your call) then why not just make some_data a #property?
class SomeConcreteClass(object):
#property
def some_data():
return 'Foo'
Alternatively, but not equivalently, you could initialize some_data for each instance within __init__.
I don't think you want to do this. Don't forget that Python is not Java ™... attributes defined at class level are class attributes, not instance attributes. You almost certainly want the data to be instance-specific, so you should do this in the __init__ method. You can certainly call the classmethod from within that method, if you want to, or (better) just put the code in __init__.

Does Python have something like anonymous inner classes of Java?

In Java you can define a new class inline using anonymous inner classes. This is useful when you need to rewrite only a single method of the class.
Suppose that you want create a subclass of OptionParser that overrides only a single method (for example exit()). In Java you can write something like this:
new OptionParser () {
public void exit() {
// body of the method
}
};
This piece of code creates a anonymous class that extends OptionParser and override only the exit() method.
There is a similar idiom in Python? Which idiom is used in these circumstances?
You can use the type(name, bases, dict) builtin function to create classes on the fly. For example:
op = type("MyOptionParser", (OptionParser,object), {"foo": lambda self: "foo" })
op().foo()
Since OptionParser isn't a new-style class, you have to explicitly include object in the list of base classes.
Java uses anonymous classes mostly to imitate closures or simply code blocks. Since in Python you can easily pass around methods there's no need for a construct as clunky as anonymous inner classes:
def printStuff():
print "hello"
def doit(what):
what()
doit(printStuff)
Edit: I'm aware that this is not what is needed in this special case. I just described the most common python solution to the problem most commonly by anonymous inner classes in Java.
You can accomplish this in three ways:
Proper subclass (of course)
a custom method that you invoke with the object as an argument
(what you probably want) -- adding a new method to an object (or replacing an existing one).
Example of option 3 (edited to remove use of "new" module -- It's deprecated, I did not know ):
import types
class someclass(object):
val = "Value"
def some_method(self):
print self.val
def some_method_upper(self):
print self.val.upper()
obj = someclass()
obj.some_method()
obj.some_method = types.MethodType(some_method_upper, obj)
obj.some_method()
Well, classes are first class objects, so you can create them in methods if you want. e.g.
from optparse import OptionParser
def make_custom_op(i):
class MyOP(OptionParser):
def exit(self):
print 'custom exit called', i
return MyOP
custom_op_class = make_custom_op(3)
custom_op = custom_op_class()
custom_op.exit() # prints 'custom exit called 3'
dir(custom_op) # shows all the regular attributes of an OptionParser
But, really, why not just define the class at the normal level? If you need to customise it, put the customisation in as arguments to __init__.
(edit: fixed typing errors in code)
Python doesn't support this directly (anonymous classes) but because of its terse syntax it isn't really necessary:
class MyOptionParser(OptionParser):
def exit(self, status=0, msg=None):
# body of method
p = MyOptionParser()
The only downside is you add MyOptionParser to your namespace, but as John Fouhy pointed out, you can hide that inside a function if you are going to do it multiple times.
Python probably has better ways to solve your problem. If you could provide more specific details of what you want to do it would help.
For example, if you need to change the method being called in a specific point in code, you can do this by passing the function as a parameter (functions are first class objects in python, you can pass them to functions, etc). You can also create anonymous lambda functions (but they're restricted to a single expression).
Also, since python is very dynamic, you can change methods of an object after it's been created object.method1 = alternative_impl1, although it's actually a bit more complicated, see gnud's answer
In python you have anonymous functions, declared using lambda statement. I do not like them very much - they are not so readable, and have limited functionality.
However, what you are talking about may be implemented in python with a completely different approach:
class a(object):
def meth_a(self):
print "a"
def meth_b(obj):
print "b"
b = a()
b.__class__.meth_a = meth_b
You can always hide class by variables:
class var(...):
pass
var = var()
instead of
var = new ...() {};
This is what you would do in Python 3.7
#!/usr/bin/env python3
class ExmapleClass:
def exit(self):
print('this should NOT print since we are going to override')
ExmapleClass= type('', (ExmapleClass,), {'exit': lambda self: print('you should see this printed only')})()
ExmapleClass.exit()
I do this in python3 usually with inner classes
class SomeSerializer():
class __Paginator(Paginator):
page_size = 10
# defining it for e.g. Rest:
pagination_class = __Paginator
# you could also be accessing it to e.g. create an instance via method:
def get_paginator(self):
return self.__Paginator()
as i used double underscore, this mixes the idea of "mangling" with inner classes, from outside you can still access the inner class with SomeSerializer._SomeSerializer__Paginator, and also subclasses, but SomeSerializer.__Paginator will not work, which might or might not be your whish if you want it a bit more "anonymous".
However I suggest to use "private" notation with a single underscore, if you do not need the mangling.
In my case, all I need is a fast subclass to set some class attributes, followed up by assigning it to the class attribute of my RestSerializer class, so the double underscore would denote to "not use it at all further" and might change to no underscores, if I start reusing it elsewhere.
Being perverse, you could use the throwaway name _ for the derived class name:
class _(OptionParser):
def exit(self):
pass # your override impl
Here is a more fancy way of doing Maciej's method.
I defined the following decorator:
def newinstance(*args, **kwargs):
def decorator(cls):
return cls(*args, **kwargs)
return decorator
The following codes are roughly equivalent (also works with args!)
// java
MyClass obj = new MyClass(arg) {
public void method() {
// body of the method
}
};
# python
#newinstance(arg)
class obj(MyClass):
def method(self):
pass # body of the method
You can use this code from within a class/method/function if you want to define an "inner" class instance.

Categories

Resources