I am programming a bokeh application. I want to split the functionalities into different files. But I want to have some attributes accesible from every class, these attributes should be shared and always updated. For example an attribute which stores a dataframe that all the plots are going to use. So I think I have at least two possible solutions:
Use a big class and include the attributes and methods of other files:
class Bigclass(object):
from bk_plots import p1, p2, p3
from bk_data import d1, d2, d3
from bk_layout import ly1, ly2
from bk_events import ev1, ev2
# unfortunately, "from classdefn import *" is an error or warning
num = 42 # add more members here if you like
Note: this solution was copied from here (partial classes)
Or I could use inheritance. The parent will have the shared attributes. The perk of this system is that I would need to send the rest of the object references to every subclass
class Parent():
shared = 'parent'
class Plot(Parent):
def __init__(self):
Parent.shared = 'plots' # update class variable from this class
# I would need to have references to the objects of other classes
class Data(Parent):
def __init__(self):
Parent.shared = 'second'
# [...]
Is there a better way to do this? Which option will bring me less problems?
Finally I have created an my_bokeh_app folder. There I have an __init__.py file with this content for the initialization:
from my_bokeh_app.bokeh_data import BokehData
from my_bokeh_app.bokeh_plots import BokehPlots
from my_bokeh_app.bokeh_table import BokehDataTable
from my_bokeh_app.bokeh_events import BokehEvents
from my_bokeh_app.bokeh_layout import BokehLayout
BokehData()
BokehPlots()
BokehDataTable()
BokehEvents()
BokehLayout()
I have created a Class to share data among all the objects. This is the class:
class BokehSharedData(object):
# ------------------- CLASS VARIABLES ---------------------- #
# This variables are shared. So all the children can access them
data_source = None
bk_layout = None
bk_data = None
bk_plot = None
bk_table = None
bk_events = None
In every class I make a reference to the BokehSharedData class. I also inherit from that class to access to the class variables.
from my_bokeh_app.bokeh_shared_data import BokehSharedData
class BokehData(BokehSharedData):
def __init__(self, **kwargs):
self.env = BokehSharedData
self.env.bk_data = self
# If for example I want to access to the source attribute from the rest of objects
# I could make this shortcut on the shared class
self.env.data_source = ColumnDataSource(...)
def update_data_source(self):
# [...]
And I could read the shared attributes or execute methods from other object:
from my_bokeh_app.bokeh_shared_data import BokehSharedData
class BokehPlots(BokehSharedData):
def __init__(self, **kwargs):
self.env = BokehSharedData
self.env.bk_plots = self
# I could use self.env.data_source here or run some method of BokehData class like this
self.env.bk_data.update_data_source()
The complete app where you can see all the classes working is here
Related
I have an interesting problem. I would like to write a class, which when inherited provides to all children classes the following behavior:
sets its self.id attribute to a UUID value
-- if this is the first time class got instantiated, a new UUID is generated
-- the UUID value is reused for the same class, when it is instantiated many times
Now, the fun part: I want the mechanism above to work, regardless of the path used to instantiate this class. Let's assume the following:
from .Package.Class1 import Class1
from TopPackage.Package.Class1 import Class1
from .Package.Class2 import Class2
from TopPackage.Package.Class2 import Class2
In both situations, I would like Class1 to generate the same self.id value in both import styles. I would also like Class2 to generate a different self.id value from Class1, but the same between its own import styles.
So far, I wrote the following code for a class classes 1 and 2 would inherit from:
class ClassWithId(ABC):
_EXISTING_OBJECT_IDS = dict()
def __init__(self):
if self in ClassWithId._EXISTING_OBJECT_IDS.keys():
self.id = ClassWithId._EXISTING_OBJECT_IDS[self]
else:
self.id = uuid.uuid4()
ClassWithId[self] = self.id
However, I have a few problems in here:
ClassWithId must inherit from class ABC because it is also an interface for classes 1 and 2
trying to put self as key in dict() results in TypeError: 'ABCMeta' object does not support item assignment
I am generally unsure, if this approach is going to be resistant to different import styles, because from Python's perspective class type .Package.Class1.Class1 and TopPackage.Package.Class1.Class1 are 2 different objects
Any ideas?
UPDATE:
I have integrated Elrond's suggestion into my code, and but different import levels (package-wise) yield different UUID values for the same class:
<class 'StageTwo.Steps.SsTestHandler1.SsTestHandler1'> 3583c89c-5ba8-4b28-a909-31cc27628370
<class 'tests.TestStages.StageTwo.Steps.SsTestHandler1.SsTestHandler1'> f4ead4a0-f5f7-4d95-8252-0de47104cb2f
<class 'StageTwo.Steps.SsTestHandler2.SsTestHandler2'> 8bd9a774-0110-4eee-a30c-a4263ad546cf
<class 'tests.TestStages.StageTwo.Steps.SsTestHandler2.SsTestHandler2'> 773d84c4-82a3-4684-92b5-51509e6db545
Maybe I forgot to mention, but my ClassWithId is inherited by ClassX and ClassY down the line, and it is these 2 classes, which are expected to be resistant to the situation I have shown above (being imported with different path, yet still retaining the same UUID).
You will need to use a metaclass for this:
import uuid
import abc
class BaseMeta(abc.ABCMeta):
def __new__(mcs, name, bases, attrs):
attrs['_class_uuid'] = uuid.uuid4()
return super().__new__(mcs, name, bases, attrs)
class Base(metaclass=BaseMeta):
def __init__(self):
print(self.__class__.__name__, self._class_uuid)
Now all classes that inherit from Base will be assigned a uuid via the _class_uuid property, once per subclass:
from package1.class1 import Class1
from package2.class2 import Class2
Class1() # 6e0852c8-61c9-4f8b-9817-eeeda4b49d56
Class1() # 6e0852c8-61c9-4f8b-9817-eeeda4b49d56
Class2() # 73012f1a-a984-4f76-96f1-ef5225a38fbe
Class2() # 73012f1a-a984-4f76-96f1-ef5225a38fbe
Using absolute/relative imports shouldn't make a difference in either case.
from Python's perspective class type .Package.Class1.Class1 and TopPackage.Package.Class1.Class1 are 2 different objects
If I understand what you're saying here, I don't think this statement is true. Hopefully, my example below will clarify.
There might be other approaches, such as using the class name as your dictionary key, but perhaps a more extendable approach is with a metaclass.
I placed everything in one file, for the sake of simplicity, but the approach remains the same for a module with multiple levels:
TopPackage.py:
import uuid
class ABC:
pass
def id_assigner(class_name, class_parents, class_attrs):
class_attrs['id'] = str(uuid.uuid4())
return type(class_name, class_parents, class_attrs)
class Class1(ABC, metaclass=id_assigner):
pass
class Class2(ABC, metaclass=id_assigner):
pass
def foo():
c2 = Class2()
print('c2.id from foo: ', c2.id)
And a script to test it:
import TopPackage
c1_a = TopPackage.Class1()
c1_b = TopPackage.Class1()
print(c1_a.id)
print(c1_b.id)
c2_a = TopPackage.Class2()
c2_b = TopPackage.Class2()
print(c2_a.id)
print(c2_b.id)
TopPackage.foo()
The call to TopPackage.foo(), I hope, shows that using Class2 from different location will result in the same class definition, and hence the same id. When I run this test script an example output I get is:
c69b17e0-9ff0-4276-bcce-6ac4f5e5a2e5
c69b17e0-9ff0-4276-bcce-6ac4f5e5a2e5
86fbe02e-d411-4ba1-b292-d2b1ec2100bd
86fbe02e-d411-4ba1-b292-d2b1ec2100bd
c2.id from foo: 86fbe02e-d411-4ba1-b292-d2b1ec2100bd
I've been googling to no avail, maybe I'm just not searching for the right thing... What I have is many subclasses from a base. This base would have a method that gets an instance of a class from an imported module. What I want is for the method in the base class to grab the instance of from the module imported in the subclass.
I have a structure like this:
root
|--Base
|----foo.py
|----bar.py
|--Child1
|----foo.py
|----bar.py
|--Child2
|----foo.py
|----bar.py
Where basically there are a few children that all inherit from Base. What I'm wondering is if it's possible to have a method inherited from Base that uses the subclass's import as such for base classes:
# file Base/foo
from root.Base import bar
class Foo(object):
def get_bar_instance(self):
return bar.Bar(param)
And:
# file Base/bar
class Bar(object):
def do_some_stuff(self):
print("Base")
And then in subclasses:
# file Child1/foo
from root.Base import foo
from root.Child1 import bar
class Foo(foo.Foo):
""" Some stuff for subclass only"""
And:
# file Child1/bar
from root.Base import bar
class Bar(bar.Bar):
def do_some_stuff(self):
print("Child1")
If I were to do:
from root.Child1 import foo
temp_foo = foo.Foo()
temp_bar = temp_foo.get_bar_instance()
temp_bar.do_some_stuff()
I would want "Child1" to be printed. Is this possible? Or is there no way to "override" a parent's imports in a submodule. It's kind of hard to explain because it isn't just a print method... I was hoping to have the method in the parent class rather than have the method in every single child
I have the following problem.
I want to have an object class, which takes as superclass a predefined object as keyword argument.
But I'm getting the error:
ImportError: cannot import name Object
Code:
import Object
class Object:
defaultobject = Object('defaultobject', None)
def __init__(self, name, superclass = defaultobject):
self.__name = name
self.__superclass = superclass
You cannot import the module you are in. You'll have to move the Object() instantiation to after the class definition:
class Object:
defaultobject = None
def __init__(self, name, superclass=None):
self.__name = name
if superclass is None:
superclass = self.defaultobject
if superclass is None
# No default set yet, use `self` instead (it'll *be* the default)
superclass = self
self.__superclass = superclass
Object.defaultobject = Object('defaultobject', None)
You can always add more attributes to a class definition, but to create an instance of a class you first need to have defined it.
The superclass is None dance is needed, because you otherwise have a catch-22 here; you cannot create an instance of Object without setting Object.defaultobject first. Which you cannot do, because you haven't created the default yet.
This issue can be solved by removing the import library from parent class which is also imported by some of its child classes. if your child class is also using import object then removing that from parent will solve the issue.
I'm doing a database insert script in pycassa. I want to set up a public static class that defines some variables that will get used a lot by other functions later on. Heres what I have...
class ks_refs():
pool = ConnectionPool('TweetsKS')
user_name_cf = self.cf_connect('UserName')
user_tweet_cf = self.cf_connect('UserTweet')
def cf_connect(column_family):
cf = pycassa.ColumnFamily(self.pool, column_family)
return cf
I haven't even tried to run this yet because I'm sure it wont work. You can see I want this static variable 'pool' first, and then set up user_name_cf and user_tweet_cf (and some more later) using the cf_connect method which needs 'pool' to work.
I know I could put that method outside the class, or I could have this non-static and make an instance of it, but I want to try this because this is what I really want (before I was just using globals but I think a static class holding all this is the best idea)
I think you want to have a class method instead:
#classmethod
def cf_connect(cls, column_family):
cf = pycassa.ColumnFamily(cls.pool, column_family)
return cf
Now you can refer to the pool defined on your class with ease.
Your user_name_cf and user_tweet_cf 'attributes' will not work, however. You can add these after having created the class definition:
class ks_refs():
pool = ConnectionPool('TweetsKS')
#classmethod
def cf_connect(cls, column_family):
cf = pycassa.ColumnFamily(cls.pool, column_family)
return cf
user_name_cf = ks_refs.cf_connect('UserName')
user_tweet_cf = ks_refs.cf_connect('UserTweet')
where they are then module-level constants, or you can add them to the class as attributes after the fact:
ks_refs.user_name_cf = ks_refs.cf_connect('UserName')
ks_refs.user_tweet_cf = ks_refs.cf_connect('UserTweet')
I want to use imports inside a class that is then inherited by another class so that I don't have to manually define my imports in each file. I am trying it like this but its not working, any advice is appreciated:
class Djangoimports ():
def __init__(self):
from django.template import Context
print Context
class Init1 (Djangoimports):
def __init__(self):
Djangoimports.__init__(self)
self.c = Context(self.constructor_dict) # just example of trying to use the imported "Context"
>>>>> global name 'Context' is not defined
I have tried variations of trying to use "self" but can't figure out how to appropriately use this with the import from as its not the same as a class attribute / method where I normally use 'self'
This works fine for me.
But you're better off doing this:
>>> class Test(object):
... from functools import partial
...
>>> Test().partial
<type 'functools.partial'>
Note that doing it your way, you have to initialize them on a per instance basis and assign to self, like so:
def Test(object):
def __init__(self):
from functools import partial
self.partial = partial
either way, you can now access bar in other methods on that class or a derived one as self.bar.
In Python, an import just adds to current namespace. The namespace is lost once you return from the function, but you can preserve the pointer appending it to 'self'.
You can do:
class Djangoimports ():
def __init__(self):
from django.template import Context
self.Context = Context
class Init1 (Djangoimports):
def __init__(self):
Djangoimports.__init__(self)
self.c = self.Context(self.constructor_dict)