I have the next code:
class PythagoreanProof(Scene):
CONFIG={
"color_triangulos":YELLOW,
"color_rect_c":RED,
"color_rect_b":ORANGE,
"color_rect_a":ORANGE,
"color_cuadrado_c":ORANGE,
"opacidad_triangulos":0.6,
"opacidad_cuadradro_a":0.6,
"opacidad_cuadradro_b":0.6,
"opacidad_cuadradro_c":0.6,
"grosor_lineas":1,
"l_a":5/5,
"l_b":12/5,
"l_c":13/5,
}
def construct(self):
self.wait()
self.pre_cuadrado()
self.pos_cuadrado()
self.tran_pre_pos_cuadrado()
self.wait()
def pre_cuadrado(self):
cuadro=Square(side_length=self.l_a+self.l_b)
As you can see, I can access the key "l_a" through self.l_a
But in this much simpler code I get the following error
class Example():
CONFIG = {'spam':25}
def __init__(self, value):
self.data = value
def display(self):
print(self.data, self.spam)
x=Example(2)
x.display()
AttributeError: 'Example' object has no attribute 'spam'
Why does it work in the first example? How does it actually work?
Thanks!
As for why is works when Scene is inherited to the class PythagoreanProof you need to have a look at the code of Scene to see what it is actually doing.
In the class Example you have defined CONFIG as a class level object. Your method display needs to point to this object with self.CONFIG and then use the key 'spam' to get its value '25'.
In order ro make the keys in CONFIG attributes you can use the #poperty wrapper.
See the example below
class Example():
CONFIG = {'spam': 25}
def __init__(self, value):
self.data = value
def display(self):
print(self.data, self.CONFIG['spam'])
#property
def spam(self):
return self.CONFIG['spam']
x = Example(2)
x.display()
print(x.spam)
2 25
25
Note some of you idents are incorrect. Method display should not be a function under __init__ but a method under class Example.
I suspect there's some magic in the Scene class that plays with the __getattr__ method. Like this :
class Scene:
# Minimalistic example.
# See https://docs.python.org/3.8/reference/datamodel.html#object.__getattr__
def __getattr__(self, name):
return self.CONFIG[name]
class Example(Scene):
CONFIG = {'spam': 25}
def __init__(self, value):
self.data = value
def display(self):
print(self.data, self.spam)
x = Example(2)
x.display()
# -> 2 25
Related
lets say we have class A and it has one instance - x. How to make a child class of class A where I would be able to pass x as an argument and get all its parameters and pass it to child class object. precisely speaking I want to do something like this.
class A:
def __init__(self, parameter1, parameter2):
self.parameter1 = parameter1
self.parameter2 = parameter2
class B(A):
def __init__(self, Ainstance, someParameter):
super().__init__(**Ainstance.__dict__)
self.someParameter = someParameter
x = A(parameter1='1', parameter2='2')
x = B(x, someParameter='3')
print(x.parameter1)
print(x.parameter2)
print(x.someParameter)
the goal is to create a class where I would be able to get all the parameters of parent class object, and add my own attributes. The problem in the code above is I won't be able to do that with all classes because not all of them has __dict__ attribute.
I have this example code which I use to remind myself how to construct a proxy.
#soProxyPattern
class Example:
def __init__(self):
self.tag_name = 'name'
def foo(self):
return 'foo'
def bar(self, param):
return param
class Container:
def __init__(self, contained):
self.contained = contained
self.user_name = 'username'
def zoo(self):
return 0
def __getattr__(self, item):
if hasattr(self.contained, item):
return getattr(self.contained,item)
#raise item
c = Container(Example())
print(c.zoo())
print(c.foo())
print(c.bar('BAR'))
print(c.tag_name)
print(c.user_name)
The output is:
0
foo
BAR
name
username
This shows that Container can have its own attributes (methods or variables) which you can access over and above all of the attributes of the contained instance.
Instead of dict you could use the dir and getattr like this:
class A:
def __init__(self, parameter1, parameter2):
self.parameter1 = parameter1
self.parameter2 = parameter2
class B(A):
def __init__(self, Ainstance, someParameter):
parameters = {param: getattr(Ainstance, param) for param in dir(Ainstance) if not param.startswith("__")}
super().__init__(**parameters)
self.someParameter = someParameter
For a more detailed explanation see: Get all object attributes in Python?
Sorry for the confusing question.
Say there are two instances of two different classes (e.g. 'big_instance' and 'little_instance').
The little_instance is defined as an attribute of the big instance.
How would a method in the little class access an attribute of the big instance.
An example is below.
The line 'return parent.attribute1' is basically pseudo code. How would this line be written properly?
class BigClass:
def __init__(self, att):
self.attribute1 = att
self.little_instance = LittleClass()
class LittleClass:
def parents_att(self):
return parent.attribute1
big_instance = BigClass(1)
print(big_instance.little_instance.parents_att())
ah yes I got it. Read the comments for explanation.
The test code at the end shows that it works even after attribute1 changes :)
class BigClass:
def __init__(self, att):
self.attribute1 = att
# pass in self
self.little_instance = LittleClass(self)
class LittleClass:
def __init__(self, the_big_class):
# the big class is held in an instance var
self.the_big_class = the_big_class
def parents_att(self):
# the instance var is used to reference the attribute
return self.the_big_class.attribute1
big_instance = BigClass(1)
print(big_instance.little_instance.parents_att())
big_instance.attribute1 = 2
print(big_instance.little_instance.parents_att())
You can do the following if you want to access attribute from BigClass into LittleClass.
class BigClass:
def __init__(self, att):
self.attribute1 = att
class LittleClass(BigClass):
def __init__(self, att):
BigClass.__init__(self, att)
def parent_att(self):
return self.attribute1
small_instance = LittleClass(1)
print(small_instance.parent_att)
I have a class which has its own methods, for example:
class Original():
def __init__(self, dummy=False):
self.dummy = dummy
def funcA(self):
print('funcA')
And I want that, in case the variable dummy is true, all the custom made functions from class Original (e.g., funcA) become dummy (i.e., don't do nothing and return nothing).
I have managed to do a dummy class like this:
class Dummy(object):
def dummy(*args, **kwargs):
pass
def __getattr__(self, _):
return self.dummy
a = Dummy()
a.asd() # returns nothing
However, I can't manage to make a class in which the writen functions work in case the variable dummy is False, and they don't if the variable is True.
Any help please?
Managed to figure it out based on Alex Hall's comment. Hope this helps anyone out there:
class Dummy(object):
def __init__(self, isDummy):
self.isDummy = isDummy
def dummy(*args, **kwargs):
pass
def __getattribute__(self, item):
if item in ['isDummy', 'dummy'] or self.isDummy is False:
attr = object.__getattribute__(self, item)
return attr
else:
return self.dummy
def funcA(self):
print('funcA')
print('Dummy:')
dummy = Dummy(isDummy=True)
dummy.funcA() # returns nothing
print('---')
print('nonDummy:')
nonDummy = Dummy(isDummy=False)
nonDummy.funcA() # prints 'funcA'
Suppose I will send self.f to a global method,
def write_to_report(file_hdlr, content):
If I want get the what the object is the file_hdlr belonged to.
How to get it ? Because I need to know the file_hanlder is belonging which Class,
and use the class name to do somthing
def write_to_report(file_hdlr, content):
file_hdlr.__self__ # ??? NO
CODE
class MemoryInfo(threading.Thread):
def __init__(self, config):
self.f = get_export_file_hdlr(self.__class__.__name__)
class CPUInfo(threading.Thread):
def __init__(self, config):
self.f = get_export_file_hdlr(self.__class__.__name__)
You can't.
A different approach:
class ReportWriterMixin(object):
def write_to_report(self):
this_class = self.__class__
# do thing with self.f based on this_class
class CPUInfo(threading.Thread, ReportWriterMixin):
def __init__(self, config):
self.f = get_export_file_hdlr(self.__class__.__name__)
self.write_to_report()
This way, while your method is no longer "global", it can be made available to any class you like
If you want to know the type of file_hdlr variable, you can use function type:
file_hdlr_type = type(file_hdlr)
This is probably a basic OO question:
I'm trying to do a nested console menu with cmd which has gone well.
I also want all my sub-consoles to have access to the same objects. This has not gone well.
My simple Example:
import cmd
class MainConsole(cmd.Cmd):
def __init__(self,obj1,obj2):
cmd.Cmd.__init__(self)
self.prompt = ">"
self.obj1 = obj1 # The objects I want access to in all my consoles.
self.obj2 = obj2
self.menu1 = SubConsole1() # I could pass in the objects here as arguments
self.menu2 = SubConsole2() # but there should be a better way.
def do_menu1(self,args):
self.menu1.cmdloop()
def do_menu2(self,args):
self.menu2.cmdloop()
def do_info(self,args):
self.menu1.do_info(args)
self.menu2.do_info(args)
def do_exit(self,args):
return -1
class SubConsole1(cmd.Cmd,MainConsole):
def __init__(self):
cmd.Cmd.__init__(self)
self.prompt = "1>"
def do_action(self,args):
print self.obj1.someattr1 # Doesn't work
class SubConsole2(cmd.Cmd,MainConsole):
def __init__(self):
cmd.Cmd.__init__(self)
self.prompt = "2>"
def do_action(self,args):
print obj1.someattr2 # Doesn't work
class anobject(object):
def __init__(self,init_value):
self.someattr1 = init_value
self.someattr2 = init_value * 2
object1 = anobject(1)
object2 = anobject(2)
c=MainConsole(object1,object2)
c.cmdloop()
When I run this I get
>
>menu1
1>info
AttributeError: SubConsole1 instance has no attribute 'obj1'
Try again.
>
>menu2
2>info
NameError: global name 'obj1' is not defined
I'm not sure if the SubConsoles should be sub-classes of MainConsole. I also tried nesting the SubConsoles inside of MainConsole.
EDIT Okay, I misunderstood what you're doing.
You are right, SubConsole1 and 2 do not need to inherit from MainConsole. But they should have a reference to the main console.
Something like:
class MainConsole(cmd.Cmd):
def __init__(self):
cmd.Cmd.__init__(self, obj1, obj2)
self.obj1 = obj2
self.obj2 = obj2
class SubConsole1(cmd.Cmd):
def __init__(self, maincon):
cmd.Cmd.__init__(self)
self.maincon = maincon
Then you can access the objects you want by accessing self.maincon.obj1 and self.maincon.obj2
The other option, and probably a better one from a design point of view, is to pull out all the objects you want to access into a Context container object, and have all the various Cmd objects maintain their own reference to that Context container.
Something like this:
import cmd
from collections import namedtuple
class MyConsole(cmd.Cmd):
def __init__(self, context):
cmd.Cmd.__init__(self)
self.context = context
class ConsoleContext(object):
def __init__(self, **kwargs):
self.__dict__ = kwargs
class MainConsole(MyConsole):
def __init__(self, context):
MyConsole.__init__(self, context)
self.menu1 = SubConsole1(context)
self.menu2 = SubConsole2(context)
self.prompt = '>'
def do_menu1(self, args):
self.menu1.cmdloop()
def do_menu2(self, args):
self.menu2.cmdloop()
def do_quit(self, args):
return True
class SubConsole1(MyConsole):
def __init__(self, context):
MyConsole.__init__(self, context)
self.prompt = '1>'
def do_action(self, args):
print self.context.message1
def do_quit(self, args):
return True
class SubConsole2(MyConsole):
def __init__(self, context):
MyConsole.__init__(self, context)
self.prompt = '2>'
def do_action(self, args):
print self.context.message2
def do_quit(self, args):
return True
if __name__ == '__main__':
context = ConsoleContext(message1='Message 1', message2='Message 2')
con = MainConsole(context)
con.cmdloop()
Hope I was clear enough.
You don't need multiple inheritance, but you need to give obj1 and obj2 to the inherited objects, except if you give some default values to obj1 and obj2.
class SubConsole1(MainConsole):
def __init__(self, obb1, obj2):
MainConsole.__init__(self, obj1, obj2)
self.prompt = "1>"
def do_action(self,args):
print self.obj1.someattr1 # Doesn't work
instanciated by :
sub1 = SubConsole1(object1, object2)
The other answer is correct insofar as you should not be using multiple inherritance, as the following is true:
class A(object):
pass
class B(A):
pass
class C(A):
pass
class D(B):
pass
a = A()
b = B()
c = C()
d = D()
isTrue = isinstance(a,A) and isinstance(b,A) and isinstance(c,A) and isinstance(d,A)
isTrue = isTrue and isinstance(b,B)and isinstance(d,B)
isTrue = isTrue and isinstance(c,C)
isTrue = isTrue and isinstance(d,D)
>>> print isTrue
True
It would also be wise to create a method of your main class wich creates subcmds, passing their reference to the subcmd's __init__ function. This way you have your object spawn its children more naturally.
class MainConsole(cmd.Cmd):
def spawnsubconsole(self):
return SubConsole1(self)
def __init__(self):
cmd.Cmd.__init__(self, obj1, obj2)
self.obj1 = obj2
self.obj2 = obj2
class SubConsole1(cmd.Cmd):
def __init__(self, maincon):
cmd.Cmd.__init__(self)
self.maincon = maincon
Then you can access the objects you want by accessing self.maincon.obj1 and self.maincon.obj2 and get the sub-cmd by running maincon.spawnsubconsole() assuming maincon is an instance of the main console class.