Why does this source code work? [duplicate] - python

This question already has an answer here:
What does "del" do exactly?
(1 answer)
Closed 6 years ago.
Some source code is like below:
class Flask(object):
def __init__(self, value):
self.value = value
def _get(self):
return self.value
def _set(self,value):
self.value = value
name = property(_get, _set)
del _get, _set
app = Flask('abc')
app.name = 'hello'
My question is why this source code block can work. Class method _get, _set was deleted by del sentences. Why we also can use app.name to call the Flask._set method?

As the comment says, they're not really deleted as there are references to them (held by the property) but they (as names) are removed from the class itself, therefore writing
app = Flask('abc')
app._get()
app._set('foo')
is not possible because Flask class no longer has these members.

del deletes the name and the memory if nothing else references it.
Since you copied the reference when doing name = property(_get, _set), del has not the effect you're believing it has (imaging the disastrous effects of a forced deletion, for instance in a C++ code. That would make the python runtime unstable)
You cannot access _get and _set methods directly (by name), but they're still referenced somewhere.
Small, simpler example:
l=[3,4,5]
x=l
del l
print(x)
print(l)
result:
[3, 4, 5] # <== x is valid
Traceback (most recent call last):
File "L:\module1.py", line 5, in <module>
print(l)
NameError: name 'l' is not defined
you see that x has kept the data. But accessing l raises NameError

Related

Instantiation of a Python class without assignment - why is the resulting object not garbage collected? [duplicate]

This question already has answers here:
Python: different behavior using gc module in interactive mode
(2 answers)
Closed 4 years ago.
Here's my problem. I fire up a fresh python console and I type in the following:
import gc
meeseeks_instance = False
class Meeseeks(object):
def __init__(self):
gc.collect()
print('Look at me!')
def __del__(self):
print('Mission accomplished!')
globals()['meeseks_instance'] = False
def __new__(cls):
gc.collect()
if globals()['meeseeks_instance']:
raise Exception('Theres already a Meeseeks!')
globals()['meeseeks_instance'] = True
return super().__new__(cls)
Now, if I type:
>>> mymeeseeks = Meeseeks()
Look at me!
>>> del mymeeseeks
Mission accomplished!
Fantastic. Now:
>>> Meeseeks()
Look at me!
<Meeseeks object at 0x043DE290>
The object was not assigned, so it's not reachable and it should be garbag collected; anyways, it seems that garbage collection was not yet run. But, if I force it, the object is correctly collected:
>>> gc.collect()
Mission accomplished!
0
And here starts the trouble. If I try to instantiate two Meeseeks, the explicit garbage collection in __new__ does not fire and the Exception is raised:
>>> Meeseeks()
Look at me!
<Meeseeks object at 0x043B0990>
>>> Meeseeks()
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "<input>", line 18, in __new__
Exception: Theres already a Meeseeks!
Why does this happen? How can I make so that trying to instantiate a new Meeseeks forces garbage collection of the previous, unreachable Meeseeks?
You made a typo of meeseks_instance in __del__, but furthermore, I think the default behavior of python's garbage collection already works as you wish.
>>> class Meeseeks(object):
... def __init__(self):
... print('Initiating %s' % self)
... def __del__(self):
... print('Deleting %s' % self)
...
>>> Meeseeks();Meeseeks()
Initiating <__main__.Meeseeks object at 0x00E88C70>
<__main__.Meeseeks object at 0x00E88C70>
Initiating <__main__.Meeseeks object at 0x00ECA1D0>
Deleting <__main__.Meeseeks object at 0x00E88C70>
<__main__.Meeseeks object at 0x00ECA1D0>

Input method in class [duplicate]

This question already has answers here:
error in python d not defined. [duplicate]
(3 answers)
Closed 8 years ago.
Class Gui: # будущее гуи, получает данные о спортсмене
# и передает в класс Person
def input(self):
self.inputName =input("name")
return self.inputName
the_app=Gui()
print the_app.input()
How to decide my problem?
Please help
now, i get this error
Traceback (most recent call last):
File "/home/julia/COURSEWORK/person.py", line 34, in <module>
print the_app.input()
File "/home/julia/COURSEWORK/person.py", line 29, in input
self.inputName =input("name")
File "<string>", line 1, in <module> NameError: name 'j' is not defined
In Python 2.x, input evaluates its input as real Python code. In other words, it is equivalent to this:
eval(raw_input())
To fix the error you showed, you need to use raw_input instead, which does not evaluate its input but returns it as a string object.
Also, Python is case-sensitive. Moreover, all keywords, including class, are lowercase. So, when you run that code, you will get a NameError saying that Class is undefined (I don't know how you got to the point you did without encountering this. Perhaps you made a typo when posting here?)
Finally, in Python 2.x, all classes should inherit from the object built-in in order to make them "new style" classes. You can read about those here.
All in all, your code should look like this:
class Gui(object): # будущее гуи, получает данные о спортсмене
# и передает в класс Person
def input(self):
self.inputName = raw_input("name")
return self.inputName
the_app = Gui()
print the_app.input()

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

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'

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

How to override built-in getattr in Python?

I know how to override an object's getattr() to handle calls to undefined object functions. However, I would like to achieve the same behavior for the builtin getattr() function. For instance, consider code like this:
call_some_undefined_function()
Normally, that simply produces an error:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'call_some_undefined_function' is not defined
I want to override getattr() so that I can intercept the call to "call_some_undefined_function()" and figure out what to do.
Is this possible?
I can only think of a way to do this by calling eval.
class Global(dict):
def undefined(self, *args, **kargs):
return u'ran undefined'
def __getitem__(self, key):
if dict.has_key(self, key):
return dict.__getitem__(self, key)
return self.undefined
src = """
def foo():
return u'ran foo'
print foo()
print callme(1,2)
"""
code = compile(src, '<no file>', 'exec')
globals = Global()
eval(code, globals)
The above outputs
ran foo
ran undefined
You haven't said why you're trying to do this. I had a use case where I wanted to be capable of handling typos that I made during interactive Python sessions, so I put this into my python startup file:
import sys
import re
def nameErrorHandler(type, value, traceback):
if not isinstance(value, NameError):
# Let the normal error handler handle this:
nameErrorHandler.originalExceptHookFunction(type, value, traceback)
name = re.search(r"'(\S+)'", value.message).group(1)
# At this point we know that there was an attempt to use name
# which ended up not being defined anywhere.
# Handle this however you want...
nameErrorHandler.originalExceptHookFunction = sys.excepthook
sys.excepthook = nameErrorHandler
Hopefully this is helpful for anyone in the future who wants to have a special error handler for undefined names... whether this is helpful for the OP or not is unknown since they never actually told us what their intended use-case was.

Categories

Resources