How can I create an object and add attributes to it?
You could use my ancient Bunch recipe, but if you don't want to make a "bunch class", a very simple one already exists in Python -- all functions can have arbitrary attributes (including lambda functions). So, the following works:
obj = someobject
obj.a = lambda: None
setattr(obj.a, 'somefield', 'somevalue')
Whether the loss of clarity compared to the venerable Bunch
recipe is OK, is a style decision I will of course leave up to you.
Python how to add an attribute to an existing object in a function
You're using getattr
and setattr
in a wrong way. The actual signatures are following:
variable = object.field ~ variable = getattr(object, 'field' [, default])
object.field = value ~ setattr(object, 'field', value)
Shortest way of creating an object with arbitrary attributes in Python?
The original code can be streamlined a little by using __dict__
:
In [1]: class data:
...: def __init__(self, **kwargs):
...: self.__dict__.update(kwargs)
...:
In [2]: d = data(foo=1, bar=2)
In [3]: d.foo
Out[3]: 1
In [4]: d.bar
Out[4]: 2
In Python 3.3 and greater, this syntax is made available by the types.SimpleNamespace
class.
Adding new attribute to an existing object
as Sami Kuhmonen says :
If Car2 inherits from Car it is a Car itself
I will detail. You said :
Now i want this method to be able to accept Car2 also and change the
way it calculates its speed. Do i need to rewrite the class and method
or is there an easier way to do it?
If you don't add methods but modify their content, you should reason by programming by interface or in more general way by programming by suitable common ancestor component.
In Java, polymorphism allows not to type specifically an instance when you declare it if a base class or an interface is more suitable.
Here :
int checkSpeed(Car c) {
speed = c.attributeX * 100
}
you can send as parameter a Car or any subclasses of it, there a Car2.
So you should keep Car
base class as declared type when it is suitable, especially in methods which may take the one or the other type.
It will work :
Car myCar = new Car();
checkSpeed(myCar);
Car2 myCar2 = new Car2();
checkSpeed(myCar2);
...
int checkSpeed(Car c) {
speed = c.attributeX * 100
}
It will not compile :
Car myCar = new Car();
checkSpeed(myCar);
Car2 myCar2 = new Car2();
checkSpeed(myCar2);
...
int checkSpeed(Car2 c) {
speed = c.attributeX * 100
}
Why is adding attributes to an already instantiated object allowed?
A leading principle is that there is no such thing as a declaration. That is, you never declare "this class has a method foo" or "instances of this class have an attribute bar", let alone making a statement about the types of objects to be stored there. You simply define a method, attribute, class, etc. and it's added. As JBernardo points out, any __init__
method does the very same thing. It wouldn't make a lot of sense to arbitrarily restrict creation of new attributes to methods with the name __init__
. And it's sometimes useful to store a function as __init__
which don't actually have that name (e.g. decorators), and such a restriction would break that.
Now, this isn't universally true. Builtin types omit this capability as an optimization. Via __slots__
, you can also prevent this on user-defined classes. But this is merely a space optimization (no need for a dictionary for every object), not a correctness thing.
If you want a safety net, well, too bad. Python does not offer one, and you cannot reasonably add one, and most importantly, it would be shunned by Python programmers who embrace the language (read: almost all of those you want to work with). Testing and discipline, still go a long way to ensuring correctness. Don't use the liberty to make up attributes outside of __init__
if it can be avoided, and do automated testing. I very rarely have an AttributeError
or a logical error due to trickery like this, and of those that happen, almost all are caught by tests.
Set a custom object attribute
The arguments passed to setCustAttr
are exactly the arguments you would pass to setattr
.
def setCustAttr(self, name, value):
setattr(self, name, value)
Why would you want a wrapper around setattr
? You might try to perform some validation:
def setCustAttr(self, name, value):
if name not in ['bar', 'baz']:
raise ValueError("Custom attribute must be 'bar' or 'baz'")
if name == 'bar' and value < 0:
raise ValueError("'bar' attribute must be non-negative")
if name == 'baz' and value % 2:
raise ValueError("'baz' attribute must be even")
setattr(self, name, value)
However, this doesn't prevent the user of your class from ignoring your setCustAttr
method and assigning directly to the object:
g = MyClass()
g.bar = -5 # Negative bar!
g.baz = 3 # Odd baz!
g.quux = 2 # Non-bar/baz attribute!
Python has deep magic for providing more control over how attributes are set on an object (see __slots__
, __{get,set}attr__
, __getattribute__
, properties, etc), but generally, they aren't used merely to prevent the examples shown above. The Python way is to just document how an instance of your class should be used, and trust the user to abide by your instructions. (And if they don't, caveat emptor.)
How can we add attribute to the Person object in the project ? Python
Do you mean something like this?
New person.py
file for experimental purposes:
class Contact:
c: str = None # contact has one attribute called c
class Person:
def __init__(self,
c=None,
driver=None,
scrape=True,
close_on_complete=True):
if c == None:
self.c = [] # use empty list
else:
self.c = c # take list from parameters
def add_c(self, c):
self.c.append(c) # append single contact to list
c1 = Contact()
c1.c = "Joe"
c2 = Contact()
c2.c = "John"
contact_list = [c1, c2]
p = Person(contact_list)
print(p.c[0].c) # print first contact
print(p.c[1].c) # print second contact
print("Again with other initialization:")
q = Person()
q.add_c(c1)
q.add_c(c2)
print(q.c[0].c) # print first contact
print(q.c[1].c) # print second contact
$ python3 person.py
Joe
John
Again with other initialization:
Joe
John
$
The error 'Person' object has no attribute 'c'
may indicate that you have an indentation problem.
Nevertheless, please try to provide a mre (https://stackoverflow.com/help/minimal-reproducible-example). Else, we cannot reproduce your error and have to guess.
New person.py
from github code (reduced, class Contact
added according to its usage):
class Contact:
c: str = None # contact has one attribute called c
def __init__(self, name):
self.c = name
class Person():
def __init__(
self,
c=None,
driver=None,
scrape=True,
close_on_complete=True,
):
self.c = c or []
def add_c(self, c):
self.c.append(c)
# name = "John Smith"
# c = Contact(name) # above was the append do not overwrite here
# self.add_c(c) # we do want to call ourselves
c1 = Contact("Joe Black")
p=Person()
p.add_c(c1)
print(p.c[0].c)
And running:
$ python3 person.py
Joe Black
$
How would I add multiple attributes together and store them in another attribute in Object Oriented Programming in Python?
Replace
return self.rent + self.laundry + self.storage + self.miscellaneousincome ==
self.totalmonthlyincome
with
self.totalmonthlyincome = self.rent + self.laundry + self.storage + self.miscellaneousincome
print(self.totalmonthlyincome)
and you should be good to go. You don't necessarily have to return something at the end of your method.
Passing attributes and methods of object inside another object
It's not totally clear, but I think this is what you want:
class PrimaryClass:
def __init__(self, param1, param2):
self.attr1 = param1
self._attr2 = do_something(param2)
def primary_method(self):
sec_cls = SecondaryClass(self)
sec_cls.secondary_method()
def __private_method(self):
do_something_else()
class SecondaryClass:
def __init__(self, primary):
self.primary = primary
def secondary_method():
print(self.primary.attr1)
print(self.primary._attr2)
To hide SecondaryClass
from users of primary_module
, use:
from secondary_module import SecondaryClass as _SecondaryClass
See Hide external modules when importing a module (e.g. regarding code-completion)
Related Topics
Why Do I Need to Deploy a "Default" App Before I Can Deploy Multiple Services in Gae
How to Make the Width of the Title Box Span the Entire Plot
Check If a Given Key Already Exists in a Dictionary and Increment It
Difference(S) Between Merge() and Concat() in Pandas
"Private" (Implementation) Class in Python
Zip with List Output Instead of Tuple
How to Include a Python Package with Hadoop Streaming Job
Pandas: Valueerror: Cannot Convert Float Nan to Integer
Destroywindow Does Not Close Window on MAC Using Python and Opencv
Return Multiple Columns from Pandas Apply()
How to Clone a Python Generator Object
How to Get the Executable's Current Directory in Py2Exe
How to Check If There Exists a Process with a Given Pid in Python
What Do All the Distributions Available in Scipy.Stats Look Like
Python Library 'Unittest': Generate Multiple Tests Programmatically