How to access objects of class and instance variable? - python

I want to know how many objects I have created in a Product class and print all names stored in the class. And is there any way to store all objects in JSON format which has been defined in Product Class?
class Product:
pass
a=Product()
a.name="Pune"
a.apple=2
b=Product()
b.name="Delhi"
b.apple=4
without assigning count in class if I want to know how much I have stored data in that class. what should I do? Is there any better way to access the "apple"
an instance variable of every instance object.
Is there any way to convert class object in JSON format like:
[{"name": "Pune", "apple":2},
{"name": "Delhi", "apple":4}]

You can use __init__ and class variable to do that.
Whenever you create an object of Product class your can add those instance variable to class list
class Product:
names = []
apples = []
def __init__(self, name, apple):
# self.name = name
# self.apple = apple
Product.names.append(name)
Product.apples.append(apple)
a=Product("Pune", 2)
b=Product("Delhi", 4)
print(Product.names)
Output:
['Pune', 'Delhi']

Related

Best way to create a list of objects?

food_data is a variable containing JSON data. Using the data, I want to create a list of Food objects, like so
foods = []
for data_row in food_data:
foods.append(Food(data_row))
This is what my Food class looks like as of right now:
class Food(dict):
""" by inheriting from dict, Food objects become automatically serializable for JSON formatting """
def __init__(self, data):
""" create a serialized food object with desired fields """
id = data["id"]
name = data["title"]
image = data["image"]
super().__init__(self, id=id, name=name, image=image)
And here is some example data:
[
{
"id": 738290,
"title": "Pasta with Garlic, Scallions, Cauliflower & Breadcrumbs",
"image": "https://spoonacular.com/recipeImages/716429-312x231.jpg",
},
{
"id": 343245,
"title": "What to make for dinner tonight?? Bruschetta Style Pork & Pasta",
"image": "https://spoonacular.com/recipeImages/715538-312x231.jpg",
}
]
Is there a method I can write for the Food class that will take the data and return a list of different versions of itself?
I would start by not subclassing dict: there is a better way to make an instance of Food serializable.
Next, make Food.__init__ dumb: three arguments, used to set three attributes.
Then, define a class method that is responsible for parsing an arbitrary dict with at least id, title, and image keys to get the values expected by Food.__init__.
Finally, define a method that turns an instance of Food back into a dict (though not necessarily the same dict that from_dict uses; generate one that serializes the way you want).
class Food:
def __init__(self, id, name, image):
self.id = id
self.name = name
self.image = image
#classmethod
def from_dict(cls, d):
return cls(id=d['id'], name=d['title'], image=d['image'])
def to_dict(self):
return dict(id=self.id, name=self.name, image=self.image)
foods = [Food.from_dict(d) for d in food_data]
To make your instance serializable, define a customer encoder that uses your to_dict method,
class FoodEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, Food):
return obj.to_dict()
return super().default(obj)
This piggy backs on the default encoder; if the immediate object is a Food, default returns a serializable dict. Otherwise, it defers to its parent to try to serialize it.
Then use that class in the call to json.dumps.
print(json.dumps(foods, cls=FoodEncoder))
I think in my case I may have been over-engineering my code. But I received many responses that did help me out in other aspects so I'm going to offer them here:
#Juanpa
Use a list comprehension
foods = [Food[data] for data in food_data]
#Chepner - unrelated but useful
subclass json.JSONEncoder instead of dict for serializability
#Matthias
Create a staticmethod within the class to return a list of objects
#staticmethod
def create_foods(food_data):
foods = []
for data_row in food_data:
foods.append(Food(data_row))

How to assign Python Dict Keys to corresponding Python Object Attributes

Suppose I have a python class like:
class User:
name = None
id = None
dob = None
def __init__(self, id):
self.id = id
Now I am doing something like this:
userObj = User(id=12) # suppose I don't have values for name and dob yet
## some code here and this code gives me name and dob data in dictionary, suppose a function call
user = get_user_data() # this returns the dictionary like {'name': 'John', 'dob': '1992-07-12'}
Now, the way to assign data to user object is userObj.name = user['name'] and userObj.dob = user['dob']. Suppose, User has 100 attributes. I will have to explicitly assign these attributes. Is there an efficient way in Python which I can use to assign the values from a dictionary to the corresponding attributes in the object? Like, name key in the dictionary is assigned to the name attribute in the object.
1. Modify the Class definition
class User():
def __init__(self, id):
self.data = {"id":id}
userObj = User(id=12)
2. Update the dict()
user = {"name":"Frank", "dob":"Whatever"} # Get the remaining data from elsewhere
userObj.data.update(user) # Update the dict in your userObj
print(userObj.data)
Here you go !
Instead of mapping a dict to the variable keys. You can use setattr to set variables in an object.
class User:
name = None
id = None
dob = None
def __init__(self, id):
self.id = id
def map_dict(self, user_info):
for k, v in user_info.items():
setattr(self, k, v)
Then for boiler code to use it.
userObj = User(id=12)
user_dict = {
'name': 'Bob',
'dob': '11-20-1993',
'something': 'blah'
}
userObj.map_dict(user_dict)
First, there is no need to predeclare properties in python.
class Foo:
bar: int # This actually creates a class member, not an instance member
...
If you want to add values to a class instance just use setattr()
d = {
'prop1': 'value1',
'prop2': 'value2',
'prop2': 'value2'
}
x = Foo()
for prop in d.keys():
setattr(x, prop, d[prop])
class User(dict):
def __init__(self, *args, **kwargs):
super(User, self).__init__(*args, **kwargs)
self.__dict__ = self
and then just get your dictionary and do:
userObj = User(dictionary)
EDIT:
user the function setattr() then
[setattr(userObj, key, item) for key,item in dict.items()]
In Case you REALLY need to
This solution is for the case, other solutions dont work for you and you cannot change your class.
Issue
In case you cannot modify your class in any way and you have a dictionary, that contains the information you want to put in your object, you can first get the custom members of your class by using the inspect module:
import inspect
import numpy as np
members = inspect.getmembers(User)
Extract your custom attributes from all members by:
allowed = ["__" not in a[0] for a in members]
and use numpy list comprehention for the extraction itself:
members = np.array(members)["__" not in a[0] for a in members]
Modify the user
So lets say you have the following user and dict and you want to change the users attributes to the values in the dictionary (behaviour for creating a new user is the same)
user = User(1)
dic = {"name":"test", "id": 2, "dob" : "any"}
then you simply use setattr():
for m in members:
setattr(user, m[0], dic[m[0]])
For sure there are better solutins, but this might come in handy in case other things dont work for you
Update
This solution uses the attribute definitions based on your class you use. So in case the dictionary has missing values, this solution might be helpful. Else Rashids solution will work well for you too

Accessing derived attributes in a named tuple from parent class

I have a simple named tuple which functions as a immutable container that characterize a class I designed.
From this Class (that has the namedtuple as class variable), I dervied multiple childclasses that all override this attribute and add new fields to the named tuple
I want to keep the fields that were defined in the Parent class ID and only add the ones that are new. I assume you could simply keep the old ID in the class and do something like ID.2nd = "added form child"
But I'd much prefere if you could simply override the ID variable and acess the previously defined ID's via a call to super() or something
from collections import namedtuple
ID = namedtuple("myTuple", ["first", "second", "third", "fourth"])
ID.__new__.__defaults__ = ("default from parentclass", None , None , None)
class Parent(object):
_ID = ID()
def __init__(self, arg):
self.arg = arg
class Child(Parent):
#if there is a new _ID defined in Child
#, keep the fields it adds but also add the
#ones from the parent:
_ID = ID(second="adding from child")
#it should now contain the fields _ID.first == "default from parent" from parentclass
#and _ID.second == "adding from child"
So far this works, but if I have another child now
class Child2(Child):
_ID = ID(third="adding from child")
#and now something like _ID.second = super()._ID.second
I will lose all information that was added in the intermediate classes.

Python class inheritance issue occurs when using base class to assign attributes of subclass

When using base class to create sub class attribute, I got an error that sub class has no member which I created in the base class method. Codes are shown below
class Base(object):
def setAttributes(self, data):
for key in data:
self.key = data[key]
class Sub(Base):
pass
data = {'id':1, 'name': 'Name'}
a = Sub()
Base.setAttributes(a, data)
print(a.id)
And the error messages are : AttributeError: 'Sub' object has no attribute 'id'.
Is there any solution to use base class to assign sub class attributes in python?
This has nothing to do with inheritance. You have assigned the value to a.key not a.id. In fact you have assigned all your values to a.key.
I believe you want setattr(self, key, data[key]) in place of self.key = data[key]. Or just do away with the loop entirely and do self.__dict__.update(data).

Python Inspect - Lookup the data type for a property in a GAE db.model Class

class Employee(db.Model):
firstname = db.StringProperty()
lastname = db.StringProperty()
address1 = db.StringProperty()
timezone = db.FloatProperty() #might be -3.5 (can contain fractions)
class TestClassAttributes(webapp.RequestHandler):
"""
Enumerate attributes of a db.Model class
"""
def get(self):
for item in Employee.properties():
self.response.out.write("<br/>" + item)
#for subitem in item.__dict__:
# self.response.out.write("<br/> --" + subitem)
The above will give me a list of the property names for the variable "item".
My idea of item.__dict__ didn't work because item was a str.
How can I then display the data field type for each property, such as db.FloatProperty() for the property called timezone?
GAE = Google App Engine - but I'm sure the same answer would work for any class.
Thanks,
Neal Walters
Iterate using "for name, property in Employee.properties().items()". The property argument is the Property instance, which you can compare using instanceof.
For problems like these, the interactive Python shell is really handy. If you had used it to poke around at your Employee object, you might have discovered the answer to your question through trial and error.
Something like:
>>> from groups.models import Group
>>> Group.properties()
{'avatar': <google.appengine.ext.db.StringProperty object at 0x19f73b0>,
'created_at': <google.appengine.ext.db.DateTimeProperty object at 0x19f7330>,
'description': <google.appengine.ext.db.TextProperty object at 0x19f7210>,
'group_type': <google.appengine.ext.db.StringProperty object at 0x19f73d0>}
From that you know that the properties() method of a db.Model object returns a dict mapping the model's property names to the actual property objects they represent.
I add the same problem, and the first 2 answers did not help me 100%.
I was not able to get the type information, from the meta data of the class or the
instance property, which is bizarre. So I had to use a dictionary.
The method GetType() will return the type of the property as a string.
Here is my answer:
class RFolder(db.Model):
def GetPropertyTypeInstance(self, pname):
for name, property in self.properties().items():
if name==pname:
return property
return None
def GetType(self, pname):
t = self.GetPropertyTypeInstance(pname)
return RFolder.__DB_PROPERTY_INFO[type(t)]
__DB_PROPERTY_INFO = {
db.StringProperty :"String",
db.ByteStringProperty :"ByteString",
db.BooleanProperty :"Boolean",
db.IntegerProperty :"Integer",
db.FloatProperty :"Float",
db.DateTimeProperty :"DateTime",
db.DateProperty :"Date",
db.TimeProperty :"Time",
db.ListProperty :"List",
db.StringListProperty :"StringList",
db.ReferenceProperty :"Reference",
db.SelfReferenceProperty :"SelfReference",
db.UserProperty :"User",
db.BlobProperty :"Blob",
db.TextProperty :"Text",
db.CategoryProperty :"Category",
db.LinkProperty :"Link",
db.EmailProperty :"Email",
db.GeoPtProperty :"GeoPt",
db.IMProperty :"IM",
db.PhoneNumberProperty :"PhoneNumber",
db.PostalAddressProperty :"PostalAddress",
db.RatingProperty :"Rating"
}

Categories

Resources