How to Create an Object and Add Attributes to It

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



Leave a reply



Submit