Dynamic inheritance method and variable in Python - python

I want use a class master to control status flag to every class which I want to maintain.
But I only find one way to dynamic add function and var like below.(staticmethod and classmethod don't work)
In my case,simple variable like integer ,float,bool can't call by object sharing
I do some research from link below, there are two ways to overcome this problem => one element list or self-defined class
Passing an integer by reference in Python
I wish can find a way perfectly inheritance just like class A(Master):
or instance_a = A(),some_fun(instance_a,Master)
help me to inheritance when creat instance
Do any one know how to achieve that
class A():
pass
class Master():
g_list = []
g_var = 0
def test_method(self,val):
print('test',val)
m_attr_list = [i for i in Master.__dict__.keys() if not i.startswith('__')]
for name in m_attr_list:
setattr(A, name, getattr( Master, name))

Related

Create Object of a Class based on another Objects Attributes in Python

What would be the best practice to create a new object, which uses the attributes of an existing object of another class type in Python?
Let's say I have an object MvsObject of the class MvsClass and I want to create a new object of a different class that uses the attributes densePointClouds and sparsePointClouds and processes them with the methods of the class PointCloud.
Would the following approach be a "good practice" in Python?
class PointCloud:
def __init__(self, MvsObject):
self.densePointClouds = MvsObject.densePointClouds
self.sparsePointClouds = MvsObject.sparsePointClouds
Your solution is good. You could also use #classmethod decorator in order to define two ways to build your class (in a "classical" way, or using another instance).
class PointCloud:
def __init__(self, dense_points_cloud, sparse_points_cloud):
self.dense_points_cloud = dense_points_cloud
self.sparse_points_cloud = sparse_points_cloud
#classmethod
def from_mvs_object(cls, mvs_object):
return cls(mvs_object.dense_points_cloud, mvs_object.sparse_points_cloud)
You would instantiate it like this:
point = PointCloud.from_mvs_object(mvs_object)
Note also I renamed the attributes because using Python, it's preferred to use snake case to name your variables.

Python class: How to check whether an attribute is defined inside __init__ or outside __init__

So if I have an class like this:
class A:
def __init__(self):
self.a = 1
obj = A()
obj.b = 2
Since I need to write a __setattr__ method to modify the attributes (ex. if it was defined inside __init__ then do something; if it was defined outside __init__ do something else. How do I determine if it was declared in init or not?
def __setattr__(self,name,value):
if name not in self.__dict__:
self.__dict__['ABC'+ name] = value # add 'ABC' before attribute's name if it was declared in __init__
else:
self.__dict__[name] = value # if it was declared outside __init__ then the attribute name doesn't change
Most of the instance attributes that you define or the parent class (or object) does are going to behave the same and be for the most part indistinguishable. If you really want to distinguish them for whatever reason, you should yourself create a way to identify them, perhaps by using a dictionary instead.
class A:
def __init__(self):
self.my_variables = {'a': 1}
# Or maintain a list with their names, it seems ugly however
self.my_variables = ['a']
With that said, I am not at all clear about why you want to do this. Maybe you should try looking for a simpler solution to the problem than overriding __setattr__.
Update:
It seems to me that you're trying to restrict updation of variables, perhaps in your attempt to create "real private variables". In my advice, don't. There's a reason that Python allows you to do a lot of things that might seem insane from point of view of Static languages. You should just start your variables with _ to mark them as private similar to what Python recommends. If people are going to access them anyway, then what's stopping them from finding a workaround to circumvent the "restrictions" that you're trying to enforce? Besides, sometimes there is a genuine justification for accessing private variables.

Can a class variable be an instance of the class?

Can a class variable of say, class Foo be a Foo object itself?
For example, I'm trying to build a class for the finite field of order 11, and I want a chosen generator (2) to be associated with this class an instance.
What I have in mind:
class FiniteField11:
generator = FiniteField11(2)
def __init__(self, element):
self.elt = element
This does not compile; I have a NameError: name 'FiniteField11' is not defined.
I realize that there is a chicken-or-egg first problem here, but is there a way to achieve what I want?
Apologies if this is a duplicate, but I can't find one.
You can do something like this:
class FiniteField11:
def __init__(self, element):
self.elt = element
FiniteField11.generator = FiniteField11(2)
Your code fails because FiniteField11 was not defined when the class defintion was parsed.
Yes it can, but the name doesn't exist until the class statement finishes. Therefore, you have to set this class variable after creating the class, perhaps just below the class block or in the instance initializer.

Nested Python class needs to access variable in enclosing class

I've seen a few "solutions" to this, but the solution every time seems to be "Don't use nested classes, define the classes outside and then use them normally". I don't like that answer, because it ignores the primary reason I chose nested classes, which is, to have a pool of constants (associated with the base class) accessible to all sub-class instances which are created.
Here is example code:
class ParentClass:
constant_pool = []
children = []
def __init__(self, stream):
self.constant_pool = ConstantPool(stream)
child_count = stream.read_ui16()
for i in range(0, child_count):
children.append(ChildClass(stream))
class ChildClass:
name = None
def __init__(self, stream):
idx = stream.read_ui16()
self.name = constant_pool[idx]
All classes are passed a single param, which is a custom bitstream class. My intention is to have a solution that does not require me to read the idx value for ChildClass while still in the ParentClass. All child-class stream reading should be done in the child class.
This example is over simplified. The constant pool is not the only variable i need available to all subclasses. The idx variable is not the only thing read from the stream reader.
Is this even possible in python? Is there no way to access the parent's information?
Despite my "bit patronizing" comment (fair play to call it that!), there are actually ways to achieve what you want: a different avenue of inheritance. A couple:
Write a decorator that introspects a class just after it's declared, finds inner classes, and copies attributes from the outer class into them.
Do the same thing with a metaclass.
Here's the decorator approach, since it's the most straightforward:
def matryoshka(cls):
# get types of classes
class classtypes:
pass
classtypes = (type, type(classtypes))
# get names of all public names in outer class
directory = [n for n in dir(cls) if not n.startswith("_")]
# get names of all non-callable attributes of outer class
attributes = [n for n in directory if not callable(getattr(cls, n))]
# get names of all inner classes
innerclasses = [n for n in directory if isinstance(getattr(cls, n), classtypes)]
# copy attributes from outer to inner classes (don't overwrite)
for c in innerclasses:
c = getattr(cls, c)
for a in attributes:
if not hasattr(c, a):
setattr(c, a, getattr(cls, a))
return cls
Here is a simple example of its use:
#matryoshka
class outer(object):
answer = 42
class inner(object):
def __call__(self):
print self.answer
outer.inner()() # 42
However, I can't help but think some of the ideas suggested in other answers would serve you better.
You don't need two classes here. Here's your example code written in a more concise fashion.
class ChildClass:
def __init__(self, stream):
idx = stream.read_ui16()
self.name = self.constant_pool[idx]
def makeChildren(stream):
ChildClass.constant_pool = ConstantPool(stream)
return [ChildClass(stream) for i in range(stream.read_ui16())]
Welcome to Python. Classes are mutable at runtime. Enjoy.
You can access the parent class through its name:
class ChildClass:
name = None
def __init__(self, stream):
idx = stream.read_ui16()
self.name = ParentClass.constant_pool[idx]
Then again, I'm not sure I understand what you are trying to achieve.
Another alternative design to consider:
When you find yourself trying to use classes as namespaces, it might make more sense to put the inner classes into a module of their own and make what were the attributes of the outer class global variables. In other words, if you never intend to instantiate your ParentClass, then it's just serving as a glorified module.
Global variables get a bad rap in most programming languages, but they are not truly global in Python, and are nicely encapsulated to the module.
Well, the following works (further simplified from your example). Note that you don't have to "declare" member variables at class level like C++/C#/Java etc, just set them on self within __init__:
class ParentClass:
def __init__(self):
self.constant_pool = ["test"]
self.ChildClass.constant_pool = self.constant_pool
self.children = [self.ChildClass()]
class ChildClass:
def __init__(self):
self.name = self.constant_pool[0]
print "child name is", self.name
p = ParentClass() # Prints "child name is test"
Note that you could still do the same sort of thing without the child classes being nested.
Your question uses the word subclass, so I'm keying from that to interpret your question. As with the others who have answered, I am not certain I understand what you are looking for.
class ParentClass(object):
constant_pool = [c1, c2, c3]
def __init__(self):
# anything not included in your question
class ChildClass(ParentClass):
def __init__(self, stream):
ParentClass.__init__(self)
self.name = ParentClass.constant_pool[stream.read_ui16()]
stream = get_new_stream()
children = []
for count in range(stream.read_ui16()):
children.append(ChildClass(stream))
This code uses inheritance to derive ChildClass from ParentClass (and all methods, etc). The constant_pool is an attribute of ParentClass itself, though it is OK to treat as an attribute of any instance of ParentClass or ChildClass (saying self.constant_pool within ChildClass.__init__ would be equivalent to the above but, in my view, misleading).
Nesting the class definitions is not necessary. Nesting the definition of ChildClass within ParentClass just means that ChildClass is an attribute of ParentClass, nothing more. It does not make instances of ChildClass inherit anything from ParentClass.

Addressing instance name string in __init__(self) in Python

I am doing something like this:
class Class(object):
def __init__(self):
self.var=#new instance name string#
How do I make the __ init __ method of my instance to use the instance name string for 'c'? Say in case:
c=Class()
I want c.var equal to 'c'.
Thanks for your replies, I am implementing persistence and Class is persistent object's class. I want __ init __ to add an entry to the database when:
c=Class()
Then, suppose:
del c
Later on:
c=Class()
sholuld create an instance using data from database if there already is an entry 'c', otherwise create new entry.
Thanks for your replies, I am implementing persistence and Class is persistent object's class. I want __ init __ to add an entry to the database when:
c=Class()
Then, suppose:
del c
Later on:
c=Class()
sholuld create an instance using data from database if there already is an entry 'c', otherwise create new entry.
Python doesn't have variables, it has objects and names. When you do
c = Class()
you're doing two things:
Creating a new object of type Class
Binding the object to the name c in the current scope.
The object you created doesn't have any concept of a "variable name" -- If later you do
a = c
then the same object is accessible in exactly the same way using the names a and c. You can delete the name a, and the object would still exist.
If the objects you create need to have a name, the best way is to pass it to them explicitly,
class Class(object):
def __init__(self, name):
self.name = name
var = Class('var')
You can't do this. The reason for this is that the object of the class is created first, and only afterwards is this object bound to the name of the instance.
You can't (short of incredible hacks like examining the stack frame and inspecting the bytecode). There may not even be a name, or there could be multiple such names. What should be given for the following code fragments for instance:
l = [Class(), Class()]
a=b=c=d=Class()
I don't think this would be possible because the assignment to the variable of your new instance occours after the object is fully constructed and initialized and so you don't know the variable name it will be assigned to within init method
To persist data objects you need to use the database record's unique ID.
pesudo code because I don't know what database module you're using
import db # assume this is your db module
class Class(object):
def __init__(self):
self.id = None
self.name = None
def get_by_id(self, id):
records = db.execute('select * from table where id=%s' % str(id))
if records:
self.id = records[0]['id']
self.name = records[0]['name']
def save(self):
db.execute('update table set name=%s where id=%s' % (self.name, str(self.id)))
Again, this is pseudo code, the string injection technique I'm using is NOT advised as its fairly insecure, its just there to illustrate how to persist using classes with a db.
I am unaware of a way to access a variable's name programmatically without using deep reflection and a debugger. I do not think the information is available at runtime.
If you want to give instances a (unique?) name, you should probably make the initializer accept an extra argument.
def __init__(self, name):
self.name = name
And the caller should pass in the appropriate name:
c = Class("c")
This is a scope issue, you can't do what you're asking. Because c would be declared outside your class' scope, your instance is unaware of what its been named in code.
Perhaps if you can provide a broader explanation of what you're trying to accomplish a better solution can be suggested.
That isn't possible. You seem to be confusing variables and objects.
In any case there may well not be a variable:
e.g.
foo(Class())
Class().arbitraryMethod()
Or multiple:
a = b = Class()
I have the same thought several years ago. This is somekind of neat feature, but the language creator doesn't provide it. And I thought they are all fool to not discover this great feature.
But then come to think about that. I think the logic is impossible. say:
class Class(object):
def __init__(self):
self.instance_name.move() # self.instance_name refer to var
def move(self):
print "move"
var = Class()
now if the var is an array is that possible too ?
var[0] = Class() # i think it will get confused a bit
that's what i think of, i don't think that assigning the instance into itself is possible. and in some language I just sent the instance string into the object then using eval to execute the function

Categories

Resources