What exactly does "AttributeError: temp instance has no attribute '__getitem__'" mean? - python

I'm trying to understand a problem I'm having with python 2.7 right now.
Here is my code from the file test.py:
class temp:
def __init__(self):
self = dict()
self[1] = 'bla'
Then, on the terminal, I enter:
from test import temp
a=temp
if I enter a I get this:
>>> a
<test.temp instance at 0x10e3387e8>
And if I try to read a[1], I get this:
>>> a[1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: temp instance has no attribute '__getitem__'
Why does this happen?

First, the code you posted cannot yield the error you noted. You have not instantiated the class; a is merely another name for temp. So your actual error message will be:
TypeError: 'classobj' object has no attribute '__getitem__'
Even if you instantiate it (a = temp()) it still won't do what you seem to expect. Assigning self = dict() merely changes the value of the variable self within your __init__() method; it does not do anything to the instance. When the __init__() method ends, this variable goes away, since you did not store it anywhere else.
It seems as if you might want to subclass dict instead:
class temp(dict):
def __init__(self):
self[1] = 'bla'

Related

types.GenericAlias - subscriptable Types and their use

I was working with namedtuples and learned something that I found odd at first. Still not quite sure how or why this works and what can be the use of this:
from collections import namedtuple
Card = namedtuple('Card', ['rank', 'suit'])
Above code works fine and creates a new Class - Card, which is a subclass of tuple class.
Now when I do this:
newCard = Card('7', 'Hearts')
It serves my purpose of creating a new card. But when I do this:
newCard = Card['7', 'Hearts']
It does not work as expected but also does not throw any error. Normally, Types are not subscriptable and if I try the same with any other class:
class FrenchDeck:
Pass
newDeck = FrenchDeck[1]
It throws following error:
Traceback (most recent call last):
File "C:\Users\sbvik\PycharmProjects\pythonProject\Chapter1.py", line 27, in <module>
c = FrenchDeck[1]
TypeError: 'type' object is not subscriptable
But if I inherit my FrenchDeck class like this:
class FrenchDeck(tuple):
Pass
newDeck = FrenchDeck[1]
No error is thrown.
Then I checked the type of newDeck it turns out to be <class 'types.GenericAlias'>
I am not sure what 'types.GenericAlias' means, what's its purpose and how is it used?
Also, why was TypeError: 'type' object is not subscriptable not thrown in this case?

Syntax Error When Importing List of Class Objects

I have a program where I want to store a list of class objects in another file. To do this i add objects to a list and then save that list to another file using this code. However, when my program tries to import the list back, it fails.
Here is my code
import sys
from test_two import *
print(test_list)
class Test:
def __init__(self):
self.number = 5
test_list = [Test(),Test(),Test()]
writing =open('test_two.py','a')
print(test_list)
writing.write("TestList = {}".format(test_list))
writing.close()
And Here is the Program storing the lists
class Test:
def __init__(self):
self.number = 5
TestList = [<__main__.Test object at 0x103acc690>, <__main__.Test object at 0x103ab38d0>, <__main__.Test object at 0x103b54750>]
However, in the original program, when i try importing i get this error
Traceback (most recent call last):
File "/Users/rudiherrig 1 2/Documents/test.py", line 2, in <module>
from test_two import *
File "/Users/rudiherrig 1 2/Documents/test_two.py", line 4
TestList = [<__main__.Test object at 0x103acc690>, <__main__.Test object at 0x103ab38d0>, <__main__.Test object at 0x103b54750>]
^
SyntaxError: invalid syntax
I have tried searching stack overflow and google for errors when lists have objects in them but could not find anything. Is that even the problem?, I am pretty sure lists can store objects but am not sure. Basically, What do you think is causing the problem?
I noticed the variable names test_list and TestList may refer to the same list, if you change TestList to test_list in your class fine, the error should disappear?
Also, if test_list were a list of strings:
test_list = ['<__main__.Test object at 0x103acc690>', '<__main__.Test object at 0x103ab38d0>', '<__main__.Test object at 0x103b54750>']
the code runs fine, creates test_two.py with these content:
TestList = [<__main__.Test object at 0x000001EE35510588>, <__main__.Test object at 0x000001EE35510508>, <__main__.Test object at 0x000001EE355105C8>]
and prints the same to terminal

Strange Nuance of self in Method Argument List

I've encountered a pythonic curiosity whose meaning eludes me.
I've found that method dispatch using a dictionary in a class appears to work differently, depending on whether the dispatch is done in __init__(). The difference is whether the selected method is invoked with or without the self argument.
Code illustration:
#!/usr/bin/python
class strange(object):
def _eek(): # no self argument
print "Hi!\n"
dsp_dict = {"Get_eek" : _eek}
noideek = dsp_dict["Get_eek"]
def __init__(self):
self.ideek = self.dsp_dict["Get_eek"]
self.ideek2 = self._eek
self.ideek3 = self.noideek
def call_ideek(self):
try:
self.ideek()
except TypeError:
print "Alas!\n"
def call_ideek2(self):
try:
self.ideek2()
except TypeError:
print "Alas!\n"
def call_ideek3(self):
try:
self.ideek3()
except TypeError:
print "Alas!\n"
def call_noideek(self):
try:
self.noideek()
except TypeError:
print "Alas!\n"
x=strange()
print "Method routed through __init__() using the dictionary:"
x.call_ideek()
print "Method routed through __init__() directly:"
x.call_ideek2()
print "Method routed through __init__() using attribute set from dictionary:"
x.call_ideek3()
print "Method not routed through __init__():"
x.call_noideek()
Running this, I see:
I, kazoo > ./curio.py
Method routed through __init__() using the dictionary:
Hi!
Method routed through __init__() directly:
Alas!
Method routed through __init__() using attribute set from dictionary:
Alas!
Method not routed through __init__():
Alas!
The try-except clauses are catching this sort of thing:
Traceback (most recent call last):
File "./curio.py", line 19, in <module>
x.call_noideek()
TypeError: call_noideek() takes no arguments (1 given)
That is, if the indirection is accomplished in __init__ by reference to the dictionary, the resulting method is not called with the implicit self argument.
But if the indirection is accomplished either in __init__ by direct reference to _eek(), or by creating a new attribute (noideek) and setting it from the dictionary, or even in __init__ by reference to the attribute originally set from the dictionary, then the self argument is in the call list.
I can work with this, but I don't understand it. Why the difference in call signature?
Have a Look at this
>>> x.ideek
<function _eek at 0x036AB130>
>>> x.ideek2
<bound method strange._eek of <__main__.strange object at 0x03562C30>>
>>> x.ideek3
<bound method strange._eek of <__main__.strange object at 0x03562C30>>
>>> x.noideek
<bound method strange._eek of <__main__.strange object at 0x03562C30>>
>>> x.dsp_dict
{'Get_eek': <function _eek at 0x036AB130>}
>>> x._eek
<bound method strange._eek of <__main__.strange object at 0x03562C30>>
You can see the difference between static methods and class methods here.
When you store the class method in that dict, it loses the information about it's enclosing class and is treated as a function (see output of x.dsp_dict).
Only if you assign that function to noideek in the class context, it will then become a class method again.
Whereas when referencing the dict from the init method, python threats it as a static method ("function") not changing anything and omnitts the self parameter. (ideek)
ideek2 and ideek3 can be seen as "aliases" where that class method is only re-referenced.

Instance object getting deleted when tried to print it

I am trying to overload new and this is my attempt:-
class String(object):
def __new__(cls, *args, **kargs):
print "in __new__"
return super(String, cls).__new__(cls)
def __init__(self):
print "Initiating instance of String"
raise Exception
def __del__(self):
print "Deleting instance of String"
I read at many places that actually __new__ create the instance and __init__ is just to initialize the instance. I am deliberately throwing exception in __init__ to let it fail. Here call to new returns the instance but init fails, so I am expecting an instance which won't have any attributes. But result surprised me like anything -
st = String()
in __new__
Initiating instance of String
Traceback (most recent call last):
File "<pyshell#89>", line 1, in <module>
st = String()
File "<pyshell#88>", line 7, in __init__
raise Exception
As expected it failed in __init__, Next I tried to print newly created instance 'st' and result surprised me, it deleted instance before printing.
>>> print st
**Deleting instance of String**
Traceback (most recent call last):
File "<pyshell#90>", line 1, in <module>
print st
NameError: name 'st' is not defined
Please help me to understand this strange behavior.
Note - I know when we should overload __new__ and when we shouldn't.
Exception was raised before Python managed to assign the object in memory to the the variable name. Therefore the reference counter of the object in memory is 0, so it got 'garbage collected', and you got name is not defined exception.
Update for the comment:
Python runs GC when it tries to allocate memory for a new object, if the threshold is filled. In your case it's probably the threshold for generation 0 that was reached, because it's where that new 'failed' String object should have been. And the event itself that triggered GC was memory allocation to execute print.

Python: dynamically add attributes to new-style class/obj

Can I dynamically add attributes to instances of a new-style class (one that derives from object)?
Details:
I'm working with an instance of sqlite3.Connection. Simply extending the class isn't an option because I don't get the instance by calling a constructor; I get it by calling sqlite3.connect().
Building a wrapper doesn't save me much of the bulk for the code I'm writing.
Python 2.7.1
Edit
Right answers all. But I still am not reaching my goal; instances of sqlite3.Connection bar my attempts to set attributes in the following ways (as do instances of object itself). I always get an AttributeError:
> conn = sqlite3.connect([filepath])
> conn.a = 'foo'
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
conn.a = 'foo'
AttributeError: 'object' object has no attribute 'a'
> conn.__setattr__('a','foo')
Traceback (most recent call last):
File "<pyshell#2>", line 1, in <module>
conn.__setattr__('a','foo')
AttributeError: 'object' object has no attribute 'a'
Help?
Yes, unless the class is using __slots__ or preventing attribute writing by overriding __setattr__, or an internal Python class, or a Python class implemented natively (usually in C).
You can always try setting an attribute. Except for seriously weird __setattr__ implementations, assigning an attribute to an instance of a class of one of the types mentioned above should raise an AttributeError.
In these cases, you'll have to use a wrapper, like this:
class AttrWrapper(object):
def __init__(self, wrapped):
self._wrapped = wrapped
def __getattr__(self, n):
return getattr(self._wrapped, n)
conn = AttrWrapper(sqlite3.connect(filepath))
Simple experimentation:
In []: class Tst(object): pass
..:
In []: t= Tst()
In []: t.attr= 'is this valid?'
In []: t.attr
Out[]: 'is this valid?'
So, indeed it seems to be possible to do that.
Update:
But from the documentation: SQLite is a C library that ..., so it seems that you really need to wrap it.
conn.a = 'foo',
or any dynamic assignment is valid, if conn is
<type 'classobj'>.
Things like:
c=object()
c.e=1
will raise an Attribute error. On the otherhand: Python allows you to do fantastic Metaclass programming:
>>>from new import classobj
>>>Foo2 = classobj('Foo2',(Foo,),{'bar':lambda self:'bar'})
>>>Foo2().bar()
>>>'bar'
>>>Foo2().say_foo()
>>>foo

Categories

Resources