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.
Related
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
so i don't know if what i am asking for is even passable or not, but never the less, i want to do is the following
class A:
def methodA(self):
pass
def methodB(self):
pass
class B:
pass
b = B()
b.methodA()
b.methodB()
but the thing is i might going to have so many number of class B objects this is why i want to assign the "A"s methods to the B class rather than to a single object of class B, i found one solution but the problem with it i have to pass the object as a parameter so for example i am going to have something like this
b.methodA(b)
b.methodB(b)
edited
so the reason why i want to do such thing is, i am making a program that will have two python interpreter whose interpreting the same python file, and i want to share objects between them by only sending/receiving the data inside the object along with the object type, so that the other interpreter will only receive the object data along with its type and make new object from class like the B class, and since both of the interpreters are interpreting the same python file, both of them will have access to the object class, so i don't really have to send the object methods, i can simply make the other interpreter copy it(if it was passable)
edited
so i will need to assign the methods and removing them in run time, and i won't be able to know what classes are the class B are going to copy methods from, until the code execution finishes
You can check Class inheritance or Polymorphism. If you have only one class that should use other's function, Inheritance is better. One will be the child of other. For example, if B will be the child of A, B will have A functions and more. read more at:
Example:
Parent
class Person:
def __init__(self, fname, lname):
self.firstname = fname
self.lastname = lname
def printname(self):
print(self.firstname, self.lastname)
#Use the Person class to create an object, and then execute the printname method:
x = Person("John", "Doe")
x.printname()
Child class:
class Student(Person):
pass
Then you could use Person's functions from Student:
x = Student("Mike", "Olsen")
x.printname()
read more: https://www.w3schools.com/python/python_inheritance.asp
You can pass class A into class B, if what you are doing is to let B have functions in A.
class A():
def method1():
return 'method1'
def method2():
return 'method2'
class B(A):
pass
B.method1()
B.method2()
I have a python class in a module, and I have a few methods within it that need to have a list of certain other classes within the same module. Here is how I'm doing it right now:
module.py
class Main:
#staticmethod
def meth1():
for c in classes:
#do something
#staticmethod
def meth2():
for c in classes:
#do something
class Class1:
pass
class Class2:
pass
class Class3:
pass
classes = [Class1, Class3]
A few things I would like to improve:
I'd like to put the classes list somewhere more prevalent. Ideally, either outside all classes, but at the top of the module file, or as a class attribute of Main, but outside of either meth1 or meth2. The purpose of that is to make it easier to find, if someone needs to add another class definition.
If possible, I'd like to do this programmatically so I don't need to explicitly define the list to begin with. This eliminates the need for #1 (though I'd still like it to be prevalent). To do this, I need a way to list all classes defined within the same module. The closest I've been able to come is dir() or locals(), but they also list imported classes, methods, and modules. Also, I would need some way to identify the classes I want. I can do that just with an attribute in the classes, but if there's some more elegant way, that would be nice.
Is what I'm trying to do even possible?
Personally, I would use a decorator to mark the classes that are important. You can place the list that will hold them at the top of the file where it will be noticable.
Here's a simple example:
# Classes are added here if they are important, because...
important_classes = []
def important(cls):
important_classes.append(cls)
return cls
#important
class ClassA(object):
pass
class ClassB(object):
pass
#important
class ClassC(object):
pass
# Now you can use the important_classes list however you like.
print(important_classes)
# => [<class '__main__.ClassA'>, <class '__main__.ClassC'>]
There may be better ways to achieve this, but I would make all of these subclasses of a holder, then use __subclasses__() to pull them all:
class Main:
def meth1(self):
for c in Holder._subclasses__():
#do something
def meth2(self):
for c in Holder._subclasses__():
#do something
class Holder(object):
pass
class Class1(Holder):
pass
class Class2(Holder):
pass
class Class3(Holder):
pass
You could even make them subclasses of Main if you wanted to, and then pull them with a classmethod:
class Main(object):
#classmethod
def meth1(cls):
for c in cls._subclasses__():
#do something
class Class1(Main): pass
You do need to inherit from object with Python 2 for this to work.
Your list seems to be targeting a subset of the available classes in the module, so at some point you will have to specify the classes you are targeting.
import sys
target_classes = ["Class1", "Class3"]
class Main:
def __init__(self, classes):
self.target_classes = classes
def meth1(self):
for s in self.target_classes:
C = getattr(sys.modules[__name__], s)
C().speak()
def meth2(self):
for c in classes:
print c
#do something
class Class1:
def speak(self):
print "woof"
class Class2:
def speak(self):
print "squeak"
class Class3:
def speak(self):
print "meow"
Main(target_classes).meth1()
--output:--
woof
meow
You can use inspect.
First, get the list of local variables:
local_vars = locals().values()
Then we need to inspect each one:
import inspect
local_vars = [i for i in local_vars if inspect.isclass(i)]
To get only classes locally defined, check if cls.__module__ == __name__ as follows:
def get_classes():
global_vars = list(globals().values())
classes = [i for i in global_vars if inspect.isclass(i)]
return [i for i in classes if i.__module__ == __name__]
The overall idea is this: inspect allows you to inspect live objects, and iterating over all local variables allows you to inspect everything within your current namespace. The final part, which classes are defined locally, can be done by checking if the module name is the same as the current namespace, or cls.__module__ == __name__.
Finally, for Python3 compatibility, I've added list(globals().values(), since the dictionary size will change during list comprehension. For Python2, since dict.values() returns a list, this can be omitted.
EDIT:
For further filtering, you can also use specific class attributes or other, as was mentioned in the comments. This is great if you are worried about restructuring your module into a package later.
def get_classes(name='target'):
global_vars = list(globals().values())
classes = [i for i in global_vars if inspect.isclass(i)]
return [i for i in classes if hasattr(i, name)]
I am not sure if this is the best practice, but this will do what you need:
class Main:
def __init__(self, locals):
self.classes = []
for (c, val) in locals.iteritems():
try:
if c[:5] == 'Class':
self.classes.append(val)
except:
pass
def meth1(self):
for c in self.classes:
pass
def meth2(self):
for c in self.classes:
pass
class Class1:
pass
class Class2:
pass
class Class3:
pass
main = Main(locals())
print main.classes
In current versions of Python you can use:
from __future__ import annotations
Is there a reasonable way in Python to implement mixin behavior similar to that found in Ruby -- that is, without using inheritance?
class Mixin(object):
def b(self): print "b()"
def c(self): print "c()"
class Foo(object):
# Somehow mix in the behavior of the Mixin class,
# so that all of the methods below will run and
# the issubclass() test will be False.
def a(self): print "a()"
f = Foo()
f.a()
f.b()
f.c()
print issubclass(Foo, Mixin)
I had a vague idea to do this with a class decorator, but my attempts led to confusion. Most of my searches on the topic have led in the direction of using inheritance (or in more complex scenarios, multiple inheritance) to achieve mixin behavior.
def mixer(*args):
"""Decorator for mixing mixins"""
def inner(cls):
for a,k in ((a,k) for a in args for k,v in vars(a).items() if callable(v)):
setattr(cls, k, getattr(a, k).im_func)
return cls
return inner
class Mixin(object):
def b(self): print "b()"
def c(self): print "c()"
class Mixin2(object):
def d(self): print "d()"
def e(self): print "e()"
#mixer(Mixin, Mixin2)
class Foo(object):
# Somehow mix in the behavior of the Mixin class,
# so that all of the methods below will run and
# the issubclass() test will be False.
def a(self): print "a()"
f = Foo()
f.a()
f.b()
f.c()
f.d()
f.e()
print issubclass(Foo, Mixin)
output:
a()
b()
c()
d()
e()
False
You can add the methods as functions:
Foo.b = Mixin.b.im_func
Foo.c = Mixin.c.im_func
I am not that familiar with Python, but from what I know about Python metaprogramming, you could actually do it pretty much the same way it is done in Ruby.
In Ruby, a module basically consists of two things: a pointer to a method dictionary and a pointer to a constant dictionary. A class consists of three things: a pointer to a method dictionary, a pointer to a constant dictionary and a pointer to the superclass.
When you mix in a module M into a class C, the following happens:
an anonymous class α is created (this is called an include class)
α's method dictionary and constant dictionary pointers are set equal to M's
α's superclass pointer is set equal to C's
C's superclass pointer is set to α
In other words: a fake class which shares its behavior with the mixin is injected into the inheritance hierarchy. So, Ruby actually does use inheritance for mixin composition.
I left out a couple of subleties above: first off, the module doesn't actually get inserted as C's superclass, it gets inserted as C's superclasses' (which is C's singleton class) superclass. And secondly, if the mixin itself has mixed in other mixins, then those also get wrapped into fake classes which get inserted directly above α, and this process is applied recursively, in case the mixed in mixins in turn have mixins.
Basically, the whole mixin hierarchy gets flattened into a straight line and spliced into the inheritance chain.
AFAIK, Python actually allows you to change a class's superclass(es) after the fact (something which Ruby does not allow you to do), and it also gives you access to a class's dict (again, something that is impossible in Ruby), so you should be able to implement this yourself.
EDIT: Fixed what could (and probably should) be construed as a bug. Now it builds a new dict and then updates that from the class's dict. This prevents mixins from overwriting methods that are defined directly on the class. The code is still untested but should work. I'm busy ATM so I'll test it later. It worked fine except for a syntax error. In retrospect, I decided that I don't like it (even after my further improvements) and much prefer my other solution even if it is more complicated. The test code for that one applies here as well but I wont duplicate it.
You could use a metaclass factory:
import inspect
def add_mixins(*mixins):
Dummy = type('Dummy', mixins, {})
d = {}
for mixin in reversed(inspect.getmro(Dummy)):
d.update(mixin.__dict__)
class WithMixins(type):
def __new__(meta, classname, bases, classdict):
d.update(classdict)
return super(WithMixins, meta).__new__(meta, classname, bases, d)
return WithMixins
then use it like:
class Foo(object):
__metaclass__ = add_mixins(Mixin1, Mixin2)
# rest of the stuff
This one is based on the way it's done in ruby as explained by Jörg W Mittag. All of the wall of code after if __name__=='__main__' is test/demo code. There's actually only 13 lines of real code to it.
import inspect
def add_mixins(*mixins):
Dummy = type('Dummy', mixins, {})
d = {}
# Now get all the class attributes. Use reversed so that conflicts
# are resolved with the proper priority. This rules out the possibility
# of the mixins calling methods from their base classes that get overridden
# using super but is necessary for the subclass check to fail. If that wasn't a
# requirement, we would just use Dummy above (or use MI directly and
# forget all the metaclass stuff).
for base in reversed(inspect.getmro(Dummy)):
d.update(base.__dict__)
# Create the mixin class. This should be equivalent to creating the
# anonymous class in Ruby.
Mixin = type('Mixin', (object,), d)
class WithMixins(type):
def __new__(meta, classname, bases, classdict):
# The check below prevents an inheritance cycle from forming which
# leads to a TypeError when trying to inherit from the resulting
# class.
if not any(issubclass(base, Mixin) for base in bases):
# This should be the the equivalent of setting the superclass
# pointers in Ruby.
bases = (Mixin,) + bases
return super(WithMixins, meta).__new__(meta, classname, bases,
classdict)
return WithMixins
if __name__ == '__main__':
class Mixin1(object):
def b(self): print "b()"
def c(self): print "c()"
class Mixin2(object):
def d(self): print "d()"
def e(self): print "e()"
class Mixin3Base(object):
def f(self): print "f()"
class Mixin3(Mixin3Base): pass
class Foo(object):
__metaclass__ = add_mixins(Mixin1, Mixin2, Mixin3)
def a(self): print "a()"
class Bar(Foo):
def f(self): print "Bar.f()"
def test_class(cls):
print "Testing {0}".format(cls.__name__)
f = cls()
f.a()
f.b()
f.c()
f.d()
f.e()
f.f()
print (issubclass(cls, Mixin1) or
issubclass(cls, Mixin2) or
issubclass(cls, Mixin3))
test_class(Foo)
test_class(Bar)
You could decorate the classes __getattr__ to check in the mixin. The problem is that all methods of the mixin would always require an object the type of the mixin as their first parameter, so you would have to decorate __init__ as well to create a mixin-object. I believe you could achieve this using a class decorator.
from functools import partial
class Mixin(object):
#staticmethod
def b(self): print "b()"
#staticmethod
def c(self): print "c()"
class Foo(object):
def __init__(self, mixin_cls):
self.delegate_cls = mixin_cls
def __getattr__(self, attr):
if hasattr(self.delegate_cls, attr):
return partial(getattr(self.delegate_cls, attr), self)
def a(self): print "a()"
f = Foo(Mixin)
f.a()
f.b()
f.c()
print issubclass(Foo, Mixin)
This basically uses the Mixin class as a container to hold ad-hoc functions (not methods) that behave like methods by taking an object instance (self) as the first argument. __getattr__ will redirect missing calls to these methods-alike functions.
This passes your simple tests as shown below. But I cannot guarantee it will do all the things you want. Make more thorough test to make sure.
$ python mixin.py
a()
b()
c()
False
Composition? It seems like that would be the simplest way to handle this: either wrap your object in a decorator or just import the methods as an object into your class definition itself. This is what I usually do: put the methods that I want to share between classes in a file and then import the file. If I want to override some behavior I import a modified file with the same method names as the same object name. It's a little sloppy, but it works.
For example, if I want the init_covers behavior from this file (bedg.py)
import cove as cov
def init_covers(n):
n.covers.append(cov.Cover((set([n.id]))))
id_list = []
for a in n.neighbors:
id_list.append(a.id)
n.covers.append(cov.Cover((set(id_list))))
def update_degree(n):
for a in n.covers:
a.degree = 0
for b in n.covers:
if a != b:
a.degree += len(a.node_list.intersection(b.node_list))
In my bar class file I would do: import bedg as foo
and then if I want to change my foo behaviors in another class that inherited bar, I write
import bild as foo
Like I say, it is sloppy.
I have a class that's being imported in module_x for instantiation, but first I want to override one of the class's methods to include a specific feature dynamically (inside some middleware that runs before module_x is loaded.
Neither AndiDog's nor Andrew's answer answer your question completely. But they have given the most important tools to be able to solve your problem (+1 to both). I will be using one of their suggestions in my answer:
You will need 3 files:
File 1: myClass.py
class C:
def func(self):
#do something
File 2: importer.py
from myClass import *
def changeFunc():
A = C()
A.func = lambda : "I like pi"
return A
if __name__ == "importer":
A = changeFunc()
File 3: module_x.py
from importer import *
print A.func()
The output of module_x would print "I like pi"
Hope this helps
You should know that each class type (like C in class C: ...) is an object, so you can simply overwrite the class methods. As long as instances don't overwrite their own methods (won't happen too often because that's not really useful for single inntances), each instance uses the methods as inherited from its class type. This way, you can even replace a method after an instance has been created.
For example:
class C:
def m(self):
print "original"
c1 = C()
c1.m() # prints "original"
def replacement(self):
print "replaced!"
C.m = replacement
c1.m() # prints "replaced!"
C().m() # prints "replaced!"
Since every python class is actually a dictionary (not only objects!)
You can easily override class methods by associate them with new function.
class A:
def f(self):
return 5
a = A()
a.f() #5
A.f = lambda self: 10
a.f() #10
You should use it with care. In most cases decorators & proper OO-design will work for you and if you forced to override class method, maybe, you make something wrong.