Are there any shortcuts for defining an empty object in Python or do you always have to create an instance of a custom empty class?
Edit: I mean an empty object usable for duck typing.
Yes, in Python 3.3 SimpleNamespace was added
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.
Example:
import types
x = types.SimpleNamespace()
x.happy = True
print(x.happy) # True
del x.happy
print(x.happy) # AttributeError. object has no attribute 'happy'
You can use type to create a new class on the fly and then instantiate it. Like so:
>>> t = type('test', (object,), {})()
>>> t
<__main__.test at 0xb615930c>
The arguments to type are: Class name, a tuple of base classes, and the object's dictionary. Which can contain functions (the object's methods) or attributes.
You can actually shorten the first line to
>>> t = type('test', (), {})()
>>> t.__class__.__bases__
(object,)
Because by default type creates new style classes that inherit from object.
type is used in Python for metaprogramming.
But if you just want to create an instance of object. Then, just create an instance of it. Like lejlot suggests.
Creating an instance of a new class like this has an important difference that may be useful.
>>> a = object()
>>> a.whoops = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'whoops'
Where as:
>>> b = type('', (), {})()
>>> b.this_works = 'cool'
>>>
One simple, less-terrifying-looking way to create an empty(-ish) object is to exploit the fact that functions are objects in Python, including Lambda Functions:
obj = lambda: None
obj.test = "Hello, world!"
For example:
In [18]: x = lambda: None
In [19]: x.test = "Hello, world!"
In [20]: x.test
Out[20]: 'Hello, world!'
You said it in the question, but as no answer mentioned it with code, this is probably one of the cleanest solutions:
class Myobject:
pass
x = Myobject()
x.test = "Hello, world!" # working
What do you mean by "empty object"? Instance of class object? You can simply run
a = object()
or maybe you mean initialization to the null reference? Then you can use
a = None
All the proposed solutions are somewhat awkward.
I found a way that is not hacky but is actually according to the original design.
>>> from mock import Mock
>>> foo = Mock(spec=['foo'], foo='foo')
>>> foo.foo
'foo'
>>> foo.bar
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/.../virtualenv/local/lib/python2.7/site-packages/mock/mock.py", line 698, in __getattr__
raise AttributeError("Mock object has no attribute %r" % name)
AttributeError: Mock object has no attribute 'bar'
See the documentation of unittest.mock here.
You can use
x = lambda: [p for p in x.__dict__.keys()]
Then
x.p1 = 2
x.p2 = "Another property"
After
x()
# gives
# ['p1', 'p2']
And
[(p, getattr(x,p)) for p in x()]
# gives
# [('p1', 2), ('p2', 'Another property')]
Constructs a new empty Set object. If the optional iterable parameter is supplied, updates the set with elements obtained from iteration. All of the elements in iterable should be immutable or be transformable to an immutable using the protocol described in section Protocol for automatic conversion to immutable.
Ex:
myobj = set()
for i in range(1,10): myobj.add(i)
print(myobj)
In my opinion, the easiest way is:
def x():pass
x.test = 'Hello, world!'
If there is a desired type of the empty object, in other words, you want to create it but don't call the __init__ initializer, you can use __new__:
class String(object):
...
uninitialized_empty_string = String.__new__(String)
Source: https://stackoverflow.com/a/2169191/6639500.
Related
Suppose I have a python object x and a string s, how do I set the attribute s on x? So:
>>> x = SomeObject()
>>> attr = 'myAttr'
>>> # magic goes here
>>> x.myAttr
'magic'
What's the magic? The goal of this, incidentally, is to cache calls to x.__getattr__().
setattr(x, attr, 'magic')
For help on it:
>>> help(setattr)
Help on built-in function setattr in module __builtin__:
setattr(...)
setattr(object, name, value)
Set a named attribute on an object; setattr(x, 'y', v) is equivalent to
``x.y = v''.
However, you should note that you can't do that to a "pure" instance of object. But it is likely you have a simple subclass of object where it will work fine. I would strongly urge the O.P. to never make instances of object like that.
Usually, we define classes for this.
class XClass( object ):
def __init__( self ):
self.myAttr= None
x= XClass()
x.myAttr= 'magic'
x.myAttr
However, you can, to an extent, do this with the setattr and getattr built-in functions. However, they don't work on instances of object directly.
>>> a= object()
>>> setattr( a, 'hi', 'mom' )
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'hi'
They do, however, work on all kinds of simple classes.
class YClass( object ):
pass
y= YClass()
setattr( y, 'myAttr', 'magic' )
y.myAttr
let x be an object then you can do it two ways
x.attr_name = s
setattr(x, 'attr_name', s)
Also works fine within a class:
def update_property(self, property, value):
setattr(self, property, value)
If you want a filename from an argument:
import sys
filename = sys.argv[1]
file = open(filename, 'r')
contents = file.read()
If you want an argument to show on your terminal (using print()):
import sys
arg = sys.argv[1]
arg1config = print(arg1config)
I have accidentally stumbled on this kind of notation:
>>> m = mock.Mock()
>>> m().my_value = 5
>>>
>>> m
<Mock id='139823798337360'>
>>> m()
<Mock name='mock()' id='139823798364240'>
m is an object of type mock, () is a function call. How can you function call an object?
I tried calling a normal object, and expectedly i got an exception
>>> class C(object):
... pass
...
>>> c = C()
>>> c()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'C' object is not callable
So this must be some kind of Mock magic. What is it and is it used for?
In Python, any object is callable if it implements __call__ method.
Any function is callable as the function object implements __call__. Also, all classes are callable. so you can make an instance of the class
In your class, if you add __call__ it'll look like this
class C(object):
def __call__(self, *args):
print("instance is called with %s", tuple(args))
Mock class defines __call__ so you can track calls to mock object.
>>> m = Mock()
>>> m(3, 4)
<Mock name='mock()' id='140219558391696'>
>>> m.mock_calls
[call(3, 4)]
>>>
I'll answer this, as it seems my question wasn't too clear.
So notation:
m = mock.Mock()
m().my_value = 5
is used to mock factory functions. When you need to mock a function that returns an object with certain properties. Every call to m() returns mock object that is different from m itself, but the same one every time (usually every call to a factory function returns a new object). So when a property of this object is set (like m().my_value=5), it will be available in any later calls to m()
If everything is object, then why won't the following code work:
x = 6
x.newAttrib = 8
So it's not an object, or some limited object?
Yes, everything is an object. However, everything being an object does not mean that everything takes arbitrary attributes.
Integers in Python are objects, and have attributes and methods (which are just callable attributes):
>>> x = 6
>>> x.real
6
>>> x.imag
0
>>> x.bit_length()
3
To support arbitrary attributes, an object needs to have a __dict__ mapping. Integers don't have such a mapping:
>>> x.__dict__
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute '__dict__'
Other objects do, like functions, for example:
>>> def foo(): pass
...
>>> foo.__dict__
{}
>>> foo.bar = 'baz'
But a __dict__ mapping comes with a price: a larger memory footprint for such objects. Since Python uses a lot of integers, it makes sense to not give them a __dict__ mapping, to save memory. You very rarely would need to give them extra attributes anyway.
You can define your own classes that produce instances without a __dict__ attribute, by giving your class a __slots__ class variable; this defines the fixed attributes an instance supports. This lets you benefit from the same memory savings:
>>> class Demo(object):
... __slots__ = ('foo',)
...
>>> d = Demo()
>>> d.foo = 'bar'
>>> d.bar = 'foo'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'Demo' object has no attribute 'bar'
And vice-versa, if you create a subclass of int and not give your subclass a __slots__ variable, you can add arbitrary attributes to that subclass:
>>> class MyInt(int):
... pass
...
>>> mi = MyInt(6)
>>> mi.foo = 'bar'
Suppose I have a python object x and a string s, how do I set the attribute s on x? So:
>>> x = SomeObject()
>>> attr = 'myAttr'
>>> # magic goes here
>>> x.myAttr
'magic'
What's the magic? The goal of this, incidentally, is to cache calls to x.__getattr__().
setattr(x, attr, 'magic')
For help on it:
>>> help(setattr)
Help on built-in function setattr in module __builtin__:
setattr(...)
setattr(object, name, value)
Set a named attribute on an object; setattr(x, 'y', v) is equivalent to
``x.y = v''.
However, you should note that you can't do that to a "pure" instance of object. But it is likely you have a simple subclass of object where it will work fine. I would strongly urge the O.P. to never make instances of object like that.
Usually, we define classes for this.
class XClass( object ):
def __init__( self ):
self.myAttr= None
x= XClass()
x.myAttr= 'magic'
x.myAttr
However, you can, to an extent, do this with the setattr and getattr built-in functions. However, they don't work on instances of object directly.
>>> a= object()
>>> setattr( a, 'hi', 'mom' )
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'hi'
They do, however, work on all kinds of simple classes.
class YClass( object ):
pass
y= YClass()
setattr( y, 'myAttr', 'magic' )
y.myAttr
let x be an object then you can do it two ways
x.attr_name = s
setattr(x, 'attr_name', s)
Also works fine within a class:
def update_property(self, property, value):
setattr(self, property, value)
If you want a filename from an argument:
import sys
filename = sys.argv[1]
file = open(filename, 'r')
contents = file.read()
If you want an argument to show on your terminal (using print()):
import sys
arg = sys.argv[1]
arg1config = print(arg1config)
I would something like this in Python:
result = SomeClass(some_argument)
Here is the catch though. I don't want the result to be an instance but an immutable object (int, for example). Basically the hole role of a class is returning a value calculated from the argument. I am using a class and not a function for DRY purposes.
Since the above code won't work because it will always return an instance of SomeClass what would be the best alternative?
My only idea is to have a static method, but I don't like it:
result = SomeClass.static_method(some_argument)
You can override __new__. This is rarely a good idea and/or necessary though ...
>>> class Foo(object):
... def __new__(cls):
... return 1
...
>>> Foo()
1
>>> type(Foo())
<type 'int'>
If you don't return an instance of cls, __init__ will never be called.
Basically class methods are the way to go if you have a factory method.
About the result - it really depends on what kind of immutability you seek, but basically namedtuple does a great job for encapsulating things and is also immutable (like normal tuples):
from collections import namedtuple
class FactoryClass(object):
_result_type = namedtuple('ProductClass', ['prod', 'sum'])
#classmethod
def make_object(cls, arg1, arg2):
return cls._result_type(prod=arg1 * arg2, sum=arg1 + arg2)
>>> FactoryClass.make_object(2,3)
ProductClass(prod=6, sum=5)
>>> x = _
>>> x.prod = 3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute