notation for accessing class and object attributes in python - python

In the following code ;
>>> class fooo():
def __init__(self):
self.a=[]
>>> fooo().a
[]
>>> fooo.a
Traceback (most recent call last):
File "<pyshell#12>", line 1, in <module>
fooo.a
AttributeError: class fooo has no attribute 'a'
i'm a little confuse about the notations fooo().a and fooo.a for accessing the variable "a".Is it that whenever we use fooo().a a object of fooo() class is thrown and it is equivalent to doing as:
>>> m=fooo()
>>> m.a
[]
; while using the notation fooo.a , we are expecting a to be a class/static variable ? Is i'm right or it is something else?

a is an instance attribute. It can be accessed using fooo().a. But note that doing that just throws away the fooo instance created; a more sensible example is:
y = fooo()
y.a = 5
It doesn't exist until an instance of the class is created. Yeah you are totally correct.

Related

If everything is an object, why can't I add attributes to some?

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'

run-time object creation in Python

I wish to make a relatively fleeting object in Python. In Javascript, which has a similar internal semantic for object management (a lookup table) you can do the following:
/* Hopefully I'm not so out of practice with JS that this would cause an error: */
var not_a_defined_class;
not_a_defined_class.this_property_exists_as_of_this_line = 1
In Python, you cannot. The equivalent would be something like the following:
not_a_defined_class = object()
not_a_defined_class.__dict__['this_property_exists_as_of_this_line'] = 1
Evidently, dot-notation to access a member of a class is syntactic sugar:
class DefinedClass(object):
__init(self):
self.predefined_property = 2
defined_object = DefinedClass()
defined_object.predefined_property = 5
# Is syntactic sugar for:
defined_object.__dict__['predefined_property'] = 5
# But is read-only
defined_object.undefined_property = 6 # AttributeError
My questions then are as follows:
Is there a difference between .__dict__['predefined_property'] = 5 and .predefined_property = 5?
Is dot-notation read-only outside class definitions (i.e. other than self.new_property =)? (As far as I can tell this is the case)
If so, why? Type safety?
Is there a way I can work around this? Is there a method called by dot-notation that I can recklessly override in my own class, say MessyObject?
Of course, I could use a dictionary object to similar effect. I'm really asking this question to learn more.
The reason you get an error is that object is a Python class defined in C. Those can't be extended. The same is true for other internal / C-based classes like str and list:
> a = 'x'
> a.foo = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'foo'
But you can extend those classes:
>>> class MyString(str): pass
...
>>> a = MyString()
>>> a.foo = 1
>>> len(a)
0
Re #1: For classes defined in Python code: Usually not. There are some corner cases which is why you should use setattr() instead.
Re #2 and #3: No. As I said above, this is only true for internal types.
Re #4: See above.

Creating an empty object in Python

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.

Python basic on classes

I have defined a class to process a file but get the following error when I try to instantiate the class and pass the filename.
Let me know what would be the problem?
>>> class fileprocess:
... def pread(self,filename):
... print filename
... f = open(filename,'w')
... print f
>>> x = fileprocess
>>> x.pread('c:/test.txt')
Traceback (most recent call last):
File "", line 1, in
TypeError: unbound method pread() must be called with
fileprocess instance as first argument (got nothing instead)
x = fileprocess does not mean x is an instance of fileprocess. It means x is now an alias for the fileprocess class.
You need to create an instance, using the ().
x = fileprocess()
x.pread('c:/test.txt')
In addition, based on your original code, you could use x to create class instances.
x = fileprocess
f = x() # creates a fileprocess
f.pread('c:/test.txt')
x = fileprocess should be x = fileprocess()
Currently x is referring to the class itself, not an instance of the class. So when you call x.pread('c:/test.txt') that's the same as calling fileprocess.pread('c:/test.txt')
But why use write mode for read function? Maybe it's pwrite?

Overwrite method at runtime in python

I have method that run many times. I dont want to nest ifs inside but rather want to overwrite method and then run it. I know that i can overwrite class method by simple assigment, but overwriten method doesn't see private members:
class X:
def __init__(self, a):
self.a = a
self.__b = a
def m(self):
print self.a
print self.__b
def a2(self):
print (2*self.a)
print (2*self.__b)
x = X(2)
x.m()
X.m = a2
x.m()
output:
2
2
4
Traceback (most recent call last):
File "t.py", line 17, in <module>
x.m()
File "t.py", line 12, in a2
print (2*self.__b)
AttributeError: X instance has no attribute '__b'
Is there any chance to solve this problem? Google doesn't show answer :(
Attributes within classes that start with double underscores are name-mangled. Never use them unless you're certain you need them. There's nothing private about them, so you should use a single underscore instead.
The reason you're having this problem is because the attribute access in a2() is not name-mangled.

Categories