Unable to access args value in python - python

I have a class Team, I want to write a Unit test for it,
class name team.py
class Team()
def __init__(self, args):
if args.player:
self.player_name = args.player
self.sports = ''
def test__init__(self):
test1 = team.Team(player="deepak")
While executing this, I am getting error like:
AttributeError: "'str' object has no attribute 'player'"
I know it is very basic but right not I need some quick help to use this. I am not aware how to access this while creating object in test file.

Arguments and keyword arguments don't work like that in python. The closest to what you want would be to use kwargs to get a dict of params.
class Team():
def __init__(self, **kwargs):
if kwargs["player"]:
self.player_name = kwargs["player"]
self.sports = ""
test1 = Team(player="deepak")
See https://docs.python.org/3/tutorial/classes.html for some good docs on how python classes work.
EDIT
Since you can't edit the code, you need to have args be an object with the member player.
from collections import namedtuple
class Team():
def __init__(self, args):
if args.player:
self.player_name = args.player
self.sports = ""
TeamArguments = namedtuple("TeamArguments", ["player"])
test1 = Team(TeamArguments(player="deepak"))

Related

How to create a class dynamically from a transformed argument collection

Pretty new to Python so the code below is pretty crude, mainly just for explaining what I have in mind.
What I am trying to do is create objects dynamically from database query. The query would return the fields needed to create the object. However, due to the use of ADO I need to transform the raw values before initialising the class.
Possible improvements to the pseudo code below would be to return the class name in the query and/or to use kwargs with the db column name as the key.
Using Python 3.6.
def main():
dbRow = GetAPersonRowFromDB()
personFromRow = CreateObjectFromDatabase(Person, dbRow, "name", "gender")
def transform(value):
transformedValue = #do something to the value
return transformedValue
def CreateObjectFromDatabase(className, *args):
transformedArgs = []
# apply transform() to each *args item
for arg in args:
transformedArgs.append(transform(dbRow[arg]))
obj = className(transformedArgs)
return obj
class Person:
def __init__(self, name, gender):
self.Name = name
self.Gender = gender
def __init__(self, *args):
self.Name = args[0]
self.Gender = args[1]
I ended up using derived classes from a base class. I'm sure it can be done in a more elegant way but this works with minimal boiler plate code.
# a dynamic object that gets constructed from kwargs
class DataObject(object):
#classmethod
def fromDictionary(cls, **kwargs):
return cls(**kwargs)
#classmethod
def type(cls):
return cls.__module__ # will only work if each class is in its own module
class Person(DataObject):
# DB column names must match parameter names
def __init__(self, name, gender):
self.Name = name
self.Gender = gender
def CreateObjectFromDatabase(className, recRow):
transformedArgs = {}
for i in range(recRow.Fields.Count):
item = recRow.Fields.Item[i]
transformedArgs[str.lower(item.Name)] = TransformSomehow(item.Value)
obj = className.fromDictionary(**transformedArgs)
return obj
def main():
dbRow = GetAPersonRowFromDB()
personFromRow = CreateObjectFromDatabase(Person, dbRow)
Was playing around with using type() method to create the object e.g.
type('Person', (DataObject, ), transformedArgs)
But this creates objects of Type 'type' which didn't work for my purpose.

How to access attribute of object from another object's method, which is one of attributes in Python?

I would like to know if it's possible, and if yes, how to access attribute(s) of a "super" class instance, when having composition implemented.
Example provided below is only to provide idea here and setup common ground on further explanations.
I want to have access to "id" attribute for an instance of MiniVan directly from object "door" (type DoorElement).
My Code
class Car:
def __init__(self, _id):
self.id = _id
class CarElement:
def __init__(self, name):
self.name = name
def get_car_id(self):
# Body which will access value of attribute "id"
return car_id
class MiniVan(Car):
def __init__(self, _id):
super(MiniVan, self).__init__(_id)
self.door = DoorElement('door')
self.engine = EngineElement('engine')
class DoorElement(CarElement):
def __init__(self, name):
super(DoorElement, self).__init__(name)
class EngineElement(CarElement):
def __init__(self, name):
super(EngineElement, self).__init__(name)
def main():
mini_van = MiniVan(123)
id_from_door = mini_van.door.get_car_id()
id_from_engine = mini_van.engine.get_car_id()
print(id_from_door) # Expected output 123
print(id_from_engine) # Expected output 123
if __name__ == '__main__':
main()
Expected:
Printed out twice "123"
What I've tried:
Passing required attribute during creating object
I know that I could just define init method with passing "car_id" but for some reasons I would love to avoid it if possible. If not, I would propably just go for it.
to set class attribute, and then call it from CarElement class within classmethod e.g.:
#classmethod
def get_id(cls):
return Car.id
But issue with this solution is that, I can have many child-classes for Car class (MiniVan, Truck, etc.) and I want have it still working.
Trying to use descriptor
def __get__(self, instance, owner):
return instance.id
But I could understand it wrong, and actually getter (as far as I understand clean code) should return instance of a class and not any attribute.
Additional Info
I will ALWAYS use CarElement (or child classes) instances as attributes of instance of Car (or child classes) instances - different usage will be treated as use-error
There can be a lot of different child classes of Car class, but always within inheritance way ( Car <- RacingCar(Car) <- FormulaOneCar(RacingCar) ) but no composition
In order for your code to work, you would have to initialize all CarElement-s with car_id. Currently, the error you are getting comes from lack of such a variable in the scope of the method. My idea of a change is this:
class CarElement:
def __init__(self, name, car_id):
self.name = name
self.car_id = car_id
def get_car_id(self):
# Body which will access value of attribute id
return self.car_id
I can't see any other magic way.

Factory method for objects with many parameters

Let me introduce my problem. I am creating a set of objects which are generally Food, but each of them might have completely different set of attributes to set.
I thought to use Factory design pattern, then i faced a problem where and how to set objects attributes and then i found some Builder pattern. However i am not sure if i am at the right path.
Example:
class Food(object):
def __init__(self, taste = None):
self._taste = taste
class Bread(Food):
def __init__(self, flour_type = None):
Food.__init__(self, taste = 'good')
self._flour = flour_type
class Meat(Food):
def __init__(self, type = None, energy_value = None, taste = None):
Food.__init__(self, taste = taste)
self._type = type
self._energy = energy_value
class Soup(Food):
def __init__(self, name = None, recipe = None):
Food.__init__(self, taste = 'fine')
self._name = name
self._recipe = recipe
and then i have a factory like this:
FOOD_TYPES = {'food':Food, 'bread':Bread, 'meat':Meat, 'soup':Soup}
class FoodFactory(object):
#staticmethod
def create_food(food_type):
try:
return FOOD_TYPES[food_type.lower()]()
except Exception:
return None
My question is: I want to pass parameters for constructors but dont know how. Is Builder pattern good idea here or not? The list of attributes might be longer. I was also wondering if passing a context dictionary with attribute name as a key and value as value.
Any ideas how to solve this? Really appreciate any hints and tips.
Regards
Just edit your FoodFactory like this:
class FoodFactory(object):
#staticmethod
def create_food(food_type, **kwargs):
try:
return FOOD_TYPES[food_type.lower()](**kwargs)
except Exception:
return None
Now you can use keyworded arguments for each Food class:
>>> meat = FoodFactory.create_food("meat", energy_value=25)
>>> print meat
>>> print meat._energy
Will print out something like:
>>> <__main__.Meat object at 0x03122AB0>
>>> 25
Hope this helps!

python - setting property of class on module loading

I'm working on a code dealing with dict data on python.
While implementing such class, I have to define a lot of properties. It's not that hard, but recently I thought it would be much better if I could use something like helper function.
For example, let's assume that I have a class like the following.
class MyClass(object):
def __init__(self, data):
self.data = data
#property
def version(self):
return self.data["version"]
If I could write this class in something like the following.
class MyClass(object):
def __init__(self, data):
self.data = data
define_own_property("data", "version")
It looks trivial, but if I can do that, I think I can reuse a lot of validation/exception handling cases.
Any idea? :D
You can achieve something like that by just writing a function to return the accessor you want:
def define_own_property(attr, key):
def prop(self):
return getattr(self, attr)[key]
return property(prop)
class MyClass(object):
def __init__(self, data):
self.data = data
version = define_own_property("data", "version")
Note that you must do version = ... There is no way to make a simple function call define_own_property add a property to the class being defined, because that class doesn't yet exist so you can't reference it.
Another possibility is to give your class an attribute that is a list or dict or something containing the relevant parameters ("data", "version", etc.), then write a class decorator that reads these parameters and auto-creates the series of properties. This would remove the need to define the properties inside the class at all; you would just give a list of the things you wanted the properties to access, and use the decorator once on the class.
It seems like you could use a descriptor:
class Descr(object):
def __init__(self,attr,key):
self.attr = attr
self.key = key
def __get__(self,obj,type=None):
return getattr(obj,self.attr)[self.key]
def __set__(self,obj,value):
getattr(obj,self.attr)[self.key] = value
def __delete__(self,obj):
del getattr(obj,self.attr)[self.key]
class MyClass(object):
def __init__(self, data):
self.data = data
version = Descr("data","version")
foobar = Descr("data","foobar")
a = MyClass({})
a.version = 1
print a.version
a.foobar = 'string'
print a.data

TypeError in Python 3.x

I have no idea what is wrong! This is a very simple program and I have done a lot head banging! Please someone enlighten me!
This a lab problem from the CSE 111 - Programming Language II course. They teach Java at the university and the code I wrote in Java works fine.
I just have to create a Student class with some fields to hold the basic information about a student with methods to get and set the attributes. Then create an instance of that class and tryout the methods.
But every time I run this program the following error occurs:
TypeError: set_name() takes exactly 1 positional argument (2 given)
Here is the code I wrote.
class Student:
'''Student class'''
name = None
id = 0
address = None
cgpa = None
def get_name():
return name
def set_name(n):
name = n
def get_id():
return id
def set_id(i):
id = i
def get_address():
return address
def set_address(a):
address = a
def get_cgpa():
return cgpa
def set_cgpa(c):
cgpa = c
#An object of Student class
jack = Student()
jack.set_name('jacky')
print(jack.get_name())
You're not accepting a reference to your instance as the first argument to that method, i.e. your set_name() should be written:
def set_name(self, n):
self.name = n
This is somewhat different from other languages where there is a built-in keyword (such as this) that refers to the current object. Python passes that reference explicitly, as an argument to the method.
All your other methods must be modified similarly.
Note that just setting name = n sets a local variable name which goes away when the method ends; it does not set anything on the instance. You have to explicitly set self.name if you want an instance attribute.
Also, and this is a matter of style, but you do not usually write set and get methods in Python. It is normal practice to set and get attributes directly. If you want to do validation of values, use a property instead. So basically, none of your methods are actually necessary in good style.
However, you don't have an __init__() method. Usually you would pass the desired attributes of the instance when instantiating the class and save these on the instance.
class Student:
def __init__(self, name, id, address, cgpa):
self.name = name
self.id = id
self.address = address
self.cgpa = cgpa
herman = Student("Herman Munster", 12345, "1313 Mockingbird Lane", 4.0)
Try this:
import sys
class Student:
'''Student class'''
self.name = None
self.id = 0
self.address = None
self.cgpa = None
def get_name(self):
return self.name
def set_name(self, n):
self.name = n
def get_id(self):
return self.id
def set_id(self, i):
self.id = i
def get_address(self):
return self.address
def set_address(self, a):
self.address = a
def get_cgpa(self):
return self.cgpa
def set_cgpa(self, c):
self.cgpa = c
You need to pass self as the first argument to each member function of the class. Member variables must then be referred to with self, i.e. self.name. Furthermore, you may wish to include an __init__() function; this serves usually to initialize any member variables, and is called at the instantiation of the class.
Take a look at the Python documentation here for some examples on well-formed classes: http://docs.python.org/tutorial/classes.html#random-remarks
In Python, you need to pass in self for each of your member functions. You also need to reference class variables as self.x, if you want them to take an effect.
Here are a couple examples that you need to apply to the rest of your code.
def set_name(self, n):
self.name = n
def get_cgpa(self):
return self.cgpa
There is some explanation for why this is the case in the documentation.
This is because first argument of methods is self - the class instance.
See What is the purpose of self?
and http://docs.python.org/tutorial/classes.html#class-objects

Categories

Resources