I am new to OOP with python. I have 3 classes with one being called from the other as a parameter instance:
class Characters:
def __init__(self, b="", c = ""):
self.b= b
self.c= c
class Words:
def __init__(self, charss=Characters()):
self.charss= charss
class Sentences:
def __init__(self, w=Words()):
self.w = w
I am then creating a new instance of class Words form another Class and filling it with data i have from a json file.
s = Sentences()
s.__dict__ = json.loads(output.content)
When debugging i can see that s is populated correctly. I am then trying to print out the values of s like this:
print(s.w[0].charss[0])
an error occurs:AttributeError: 'dict' object has no attribute 'charss'
is it because I am populating from the JSON as __dict__ where charss instantiated as list. If that is so what would be the best solution changing the __dict__ from json input or instantiating the object as __dict__?
The problem is the way the instance s is being accessed for printing. I am saving the json output as a dictionary but the instance of a class is by default a list. therefore instead of
print(s.w[0].charss[0])
that line should be
print(s.w[0]["charss"][0])
When you say s.__dict__ = some_dictionary, you're entirely replacing all the instance variables of s with the ones in some_dictionary. This includes w, which is now defined entirely by whatever's in your JSON. JSON objects are never going to have charss attributes, so it's guaranteed to fail in the way you mention.
What are you trying to accomplish with s.__dict__ = json.loads(output.content)? Do you just want to store the dictionary in s? If so, s.my_cool_dict_name = json.loads(output.content) might be what you want.
Related
I have a comprehension problem in python, maybe there is a simple solution for it, or maybe a design pattern.
class SampleClass:
__dictionary = dict()
def __init__(self, sentence: dict):
self.__dictionary = sentence
def get_a(self):
def transform_to_another_object():
# call some other methods which return a new object
return self.__dictionary["a"]
def get_b(self):
def transform_to_another_object():
# call some other methods which return a new object
return self.__dictionary["b"]
def get_c(self):
def transform_to_another_object():
# call some other methods which return a new object
return self.__dictionary["c"]
if __name__ == '__main__':
example = {"a": {"SampleObjectA"}, "b": {"SampleObjectA"}, "c": {"SampleObjectA"}}
sample = SampleClass(example)
new_object_a = sample.get_a().transform_to_another_object() #returns the tranfrmed object
object_a = sample.get_a() # return the original Object
new_object_b = sample.get_b().transform_to_another_object()
object_b = sample.get_b()
that was my idea until now.
The class actually generates a large dictionary, which is always built the same way (with the same keys). The stored element should then be able to be transformed into a new object with a transform method. So from the XML element to an custom object.
I hope I have explained this in a reasonably understandable way.
Maybe it is the completely wrong approach, in any case I am glad about your help.
Update
The original class is part of a backend of a web-based application.
Normally the __init__ method of the class takes a path and then reads an xml file (this is always built the same way, so same tags).
This file is then read and separated into its tags and stored in a dictionary. Each dictionary key contains an xml element.
With a get method now the single xml elements are to be accessed, in order to be able to convert these afterwards into an own object.
How can I create an object, while also passing to its __init__ all the keywords and their values of another object? Basically this:
class Person():
instances = []
def __init__(self,**kwargs):
self.__dict__.update(**kwargs)
__class__.instances.append(self)
class TemplatePerson():
instances = []
def __init__(self,**kwargs):
self.__dict__.update(**kwargs)
__class__.instances.append(self)
def foo(template):
# I want this function to basically execute what would be:
# Person(name="Alice",surname="Bobbette")
# except dynamically for all the keywords and values the template object could have
pass
foo(TemplatePerson(name="Alice",surname="Bobbette"))
I stumbled upon __dict__, but don't know how to utilize it. It's important that all the keywords are passed to the new object on its initialization, rather than do something like:
Person.name="Alice"
Person.surname="Bobbette
because my Person.__init__ is a mess ;)
Thanks in advance.
I successfully print a list of keys to the screen and then ask the user to type in a key name to get a specific object. This is the way i thought it worked:
print dict['bob']
and this would output the object stored with the 'bob' key however it does not. I'm assuming this problem arises because im storing objects and not strings or ints. If the name entered is a key it just prints the name again not the object and if it isn't a key it throws an error. The end result of this is to get a specified object so the user can view that objects attributes.
When the above statement is ran it just prints the key to the screen:
bob
printing my dictionary looks like this
{'Sal': <Employ_Class2.Employee object at 0x01EE38F0>, 'bob': <Emplo
y_Class2.Employee object at 0x01EE3930>, 'jack': <Employ_Class2.Employee o
bject at 0x01EE3990>, 'alexa': <Employ_Class2.Employee object at 0x01EE3870>,
'dave': <Employ_Class2.Employee object at 0x01EE3910>, 'sew
': <Employ_Class2.Employee object at 0x01EE3950>, 'tam': <Employ_Class2.Em
ployee object at 0x01EE39D0>}
It looks like you're simply being misled by the fact that print obj prints the result of calling the object's __str__ or __unicode__ methods. So, the object in the dictionary under the key "bob", when converted to string, is simply "bob".
As others have said, if you simply want to print the attributes of the object under that key, use dir:
obj = dict['bob']
print dir(obj)
If you want to view the names of the attributes of the object, use dir().
If the dictionary contains the instances of the class you've created and you want to extract relevant information from those objects, you need to create in your class a function which does that and invoke it later.
Suppose you have an object of type Product, given that Product is the class you've created. You store multiple products in your dictionary. What do you want to get back? The name of the product? The name, the price and the description? Or maybe the class name? Python won't be able to figure out your intention, so it's up to you to either create a specific method which does what you want it to do, or use __str__().
I think what you wanted is dir([object]) .
Without arguments, return the list of names in the current local scope. With an argument, attempt to return a list of valid attributes for that object.
So according to the documentation you can have the attributes fro that object with dir().
Hope this is what you have wanted..
Not sure if you are referring to object attributes you are defining in your class definition or the names you would find with dir(). In either case, if your object class has a __str__ or __repr__ methods defined, those will be called when using print. If you want a user to be able to view the names in the object space, just use dir(). If you want them to access attributes and properties you set in the class definition, access them directly (or through whatever methods you created to do so:
class Test:
attr = 'item' # this is a class attribute
def __init__(self):
self.name = 'Me' # this will be an instance variable/property
def __str__(self):
return self.name
d = {} # example does not need a dict but using one to relate to posted question
d['item'] = Test()
print(d['item'])
results in self.name being printed to screen:
dir(d['item']) will instead print out all of the names in the object namespace, including methods and attributes.
To print your created attributes (attr and self.name above), then you can simply do:
print(d['item'].attr)
print(d['item'].name)
So, in that case, your users should just access the dict objects directly: dict['bob'].attribute
Hope that makes some sense.
I was wandering how does elixir\sqlalchemy get to know all the entity classes I've declared in my model, when I call setup_all()? I need that kind of functionality in a little project of mine, but I have no clue. I've tried to steptrace through elixir's setup_all(), and I found that it keeps a collection of all entity classes in a "global" list (or was it dict?), but I can't catch the moment when the list is filled. Any ideas?
For class definitions, this is easier (no importing)
def find_subclasses(cls):
results = []
for sc in cls.__subclasses__():
results.append(sc)
return results
I'm not sure if you wanted this, or objects. If you want objects:
import gc
def find_subclasses(cls):
results = []
for sc in cls.__subclasses__():
for obj in gc.get_objects():
if isinstance(obj, sc):
results.append(obj)
return results
Answering the main question, without dealign with SQLALchemy or elixir at all - yes, it is possible in Python.
The garbage colector (gc) module on the standard library, have a function call that allows one to retrieve all references to a given object, interpreter wide. A class is always referred to in the __mro__ attribute of any inherited classes.
So, the following function could retrieve all classes that inherit from a given class:
import gc
def find_subclasses(cls):
all_refs = gc.get_referrers(cls)
results = []
for obj in all_refs:
# __mro__ attributes are tuples
# and if a tuple is found here, the given class is one of its members
if (isinstance(obj, tuple) and
# check if the found tuple is the __mro__ attribute of a class
getattr(obj[0], "__mro__", None) is obj):
results.append(obj[0])
return results
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