Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a new unknown or dynamic/expando object in Python

In python how can we create a new object without having a predefined Class and later dynamically add properties to it ?

example:

dynamic_object = Dynamic() dynamic_object.dynamic_property_a = "abc" dynamic_object.dynamic_property_b = "abcdefg" 

What is the best way to do it?

EDIT Because many people advised in comments that I might not need this.

The thing is that I have a function that serializes an object's properties. For that reason, I don't want to create an object of the expected class due to some constructor restrictions, but instead create a similar one, let's say like a mock, add any "custom" properties I need, then feed it back to the function.

like image 848
Jimmy Kane Avatar asked Dec 23 '12 23:12

Jimmy Kane


People also ask

How do you create a dynamic object in Python?

Python Code can be dynamically imported and classes can be dynamically created at run-time. Classes can be dynamically created using the type() function in Python. The type() function is used to return the type of the object. The above syntax returns the type of object.

How do you create a dynamic object?

You can create custom dynamic objects by using the classes in the System. Dynamic namespace. For example, you can create an ExpandoObject and specify the members of that object at run time. You can also create your own type that inherits the DynamicObject class.

Can we create object without class in Python?

We already know that an object is a container of some data and methods that operate on that data. In Python, an object is created from a class. To create an object, you have to define a class first.


2 Answers

Just define your own class to do it:

class Expando(object):     pass  ex = Expando() ex.foo = 17 ex.bar = "Hello" 
like image 158
Ned Batchelder Avatar answered Oct 07 '22 01:10

Ned Batchelder


If you take metaclassing approach from @Martijn's answer, @Ned's answer can be rewritten shorter (though it's obviously less readable, but does the same thing).

obj = type('Expando', (object,), {})() obj.foo = 71 obj.bar = 'World' 

Or just, which does the same as above using dict argument:

obj = type('Expando', (object,), {'foo': 71, 'bar': 'World'})() 

For Python 3, passing object to bases argument is not necessary (see type documentation).

But for simple cases instantiation doesn't have any benefit, so is okay to do:

ns = type('Expando', (object,), {'foo': 71, 'bar': 'World'}) 

At the same time, personally I prefer a plain class (i.e. without instantiation) for ad-hoc test configuration cases as simplest and readable:

class ns:     foo = 71     bar = 'World' 

Update

In Python 3.3+ there is exactly what OP asks for, types.SimpleNamespace. It's just:

A simple object subclass that provides attribute access to its namespace, as well as a meaningful repr.

Unlike object, with SimpleNamespace you can add and remove attributes. If a SimpleNamespace object is initialized with keyword arguments, those are directly added to the underlying namespace.

import types obj = types.SimpleNamespace() obj.a = 123 print(obj.a) # 123 print(repr(obj)) # namespace(a=123) 

However, in stdlib of both Python 2 and Python 3 there's argparse.Namespace, which has the same purpose:

Simple object for storing attributes.

Implements equality by attribute names and values, and provides a simple string representation.

import argparse obj = argparse.Namespace() obj.a = 123 print(obj.a) # 123  print(repr(obj)) # Namespace(a=123) 

Note that both can be initialised with keyword arguments:

types.SimpleNamespace(a = 'foo',b = 123) argparse.Namespace(a = 'foo',b = 123) 
like image 20
saaj Avatar answered Oct 07 '22 00:10

saaj