Cannot access class variable in class method - python

class Bin():
a=[]
def g(self,e):
self.a.append(e)
o=Bin()
o.g(3)
o.g(4)
o.g(5)
o.g(6)
Traceback (most recent call last):
File "<string>", line 28, in <module>
File "<string>", line 9, in bs
NameError: name 'a' is not defined
how to deal with this error? i wanna append the list inside the class with given elements and use the list 'a' in other class methods too.

Fix your indentation:
class Bin:
a = []
def g(self, e):
self.a.append(e)
o = Bin()
o.g(3)
o.g(4)
o.g(5)
o.g(6)
print(Bin.a)
Output : [3, 4, 5, 6]

Related

Change builtin function - Print

I'm trying to change the print builtin function from python.
The reason I'm trying to achieve this is cause my application has an verbose sys.argv, and I want to use print to console out the message whether the verbose is True or False.
I've tried to use create a new function, but I get a recursion error:
>>> import builtins
>>> def new_print(*args, **kwargs):
... print('print:', *args, **kwargs)
...
>>> old_print = builtins.print
>>> old_print(1)
1
>>> builtins.print = new_print
>>> print(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in new_print
File "<stdin>", line 2, in new_print
File "<stdin>", line 2, in new_print
[Previous line repeated 996 more times]
RecursionError: maximum recursion depth exceeded
I've tried using sys.stdout():
>>> import builtins
>>> import sys
>>> def new_print(*args, **kwargs):
... sys.stdout(*args, **kwargs)
...
>>> old_print = builtins.print
>>> old_print(1)
1
>>> builtins.print = new_print
>>> print(1
... )
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in new_print
TypeError: '_io.TextIOWrapper' object is not callable
Although using those options, none seemed to work properly.
I need the new print function to be accesible for all my module files, without needing to import it every time. That's why I'm trying to change the builtin function, but I'm not sure that changing this in my init.py file will make a difference for my other files.
Please, if you have any idea on what could help me, please leave it below.
You almost had it. Call old_print in your new function:
def new_print(*args, **kwargs):
old_print('print:', *args, **kwargs)
old_print = print
print = new_print

Is it possible to define a function in a Class

I have a problem with my python code specialy when I'm trying to define a function in a Class. Indeed, I want to call this function (which is in a file i called BC.py) in my main program which i called PBC.py
Class BC():
self.nmodes
self.L_ch
self.w
def func1(self,x):
self.k_ch=self.nmodes*self.L_ch*self.w
f=x**3+4*x*self.k_ch+15*self.k_ch
return f
In my main programm i did:
from BC import *
A=BC()
C=func1(self,x)
Then I got this error:
The parameters file have been imported succesfully
Traceback (most recent call last):
File "PBC.py", line 35, in <module>
C =func1(A,eps)
NameError: name 'func1' is not defined
Please do you know where i am wrong?
The thing is, when i don't include the function in my class everything works well,
Class BC():
self.nmodes
self.L_ch
self.w
def func1(self,x):
self.k_ch=self.nmodes*self.L_ch*self.w
f=x**3+4*x+15
return f
Exept that when i use only the function, all the parameters I defined before are not recognized???
For example:
r_0=scipy.optimize.fsolve(func1,0.003,args=(0.032))
I got this error:
The parameters file have been imported succesfully
Traceback (most recent call last):
File "PBC.py", line 75, in <module>
R_0=scipy.optimize.fsolve(func1,float(eps_real),args=(eps))
File "/usr/local/lib64/python2.7/site-packages/scipy/optimize/minpack.py", line 127, in fsolve
res = _root_hybr(func, x0, args, jac=fprime, **options)
File "/usr/local/lib64/python2.7/site-packages/scipy/optimize/minpack.py", line 183, in _root_hybr
_check_func('fsolve', 'func', func, x0, args, n, (n,))
File "/usr/local/lib64/python2.7/site-packages/scipy/optimize/minpack.py", line 14, in _check_func
res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
File "/home/cfd1/ndiaye/ATACAMAC/BCT_dev.py", line 75, in func1
self.k_ch=self.nmodes*self.pi/self.L_ch+eps/self.L_ch
AttributeError: 'numpy.ndarray' object has no attribute 'nmodes'
Someone can help?
Thank you very much.
Thank you for your answer but it isn't working, i still got this error:
Traceback (most recent call last):
File "PBC.py", line 36, in <module>
C =A.func1(x)
Now i'm trying with a very simplified script:
class real :
def __init__(self):
self.nmodes = 4
self.L_ch = 1
self.w = 2
def func1(self,x):
self.k_ch=self.nmodes*self.L_ch*self.w
f=x**3+4*x*self.k_ch+15*self.k_ch
return f
And my main program is:
from dev import *
A=real()
C=A.func1(x)
Unfortunately it seems not working to caus' i have the same traceback error.
Thank you.
You should call it this way:
from BC import *
A=BC()
C=A.func1(x)
Edit for comment:
Please take care of the code format:
class real :
def __init__(self):
self.nmodes = 4
self.L_ch = 1
self.w = 2
def func1(self,x):
self.k_ch=self.nmodes*self.L_ch*self.w
f=x**3+4*x*self.k_ch+15*self.k_ch
return f
Call the function this way (recommended):
A = BC()
C = A.func1(x)
or this other (less used and not recommended, just mentioned as information):
C = BC.func1(A, x)
Note: I would recommend you to rename your file with a name different than the class BC, because it confuses Python. Also, don't forget to declare x.

Accessing instance variables using index

I have a class which keeps track of errors encountered during a search operation
class SearchError(object):
def __init__(self,severity=0,message=''):
self.severity = severity
self.message = message
My idea is to make the instance variables indexable.
So if I have
a=SearchError(1,"Fatal Error")
I get
>>> a[0]
1
>>> a[1]
'Fatal Error'
>>> a.severity
1
>>> a.message
'Fatal Error'
To do this I add a __getitem__ method to the class. The class now becomes
class SearchError(object):
def __init__(self,severity=0,message=''):
self.severity = severity
self.message = message
def __getitem__(self,val):
if isinstance(val,slice):
return [self.__getitem__(i) for i in xrange(val.start,val.stop,val.step)]
elif val==0:
return self.severity
elif val==1:
return self.message
else:
raise IndexError
This does what I want but fails in cases such as
>>> a[:2]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 23, in __getitem__
TypeError: an integer is required
Or even
>>> a[-1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 29, in __getitem__
IndexError
I understand my implementation of __getitem__ is limited. What I need to know is -
Is this the way to make instance variables indexable (Without using a list as variable container)?
How do I make the object behave 'sanely' as far as indexing goes?
This does everything:
>>> from collections import namedtuple
>>> _SearchError = namedtuple("SearchError", "severity message")
>>> def SearchError(severity=0, message=''):
return _SearchError(severity, message)
xrange requires all its arguments to be integers, but slice objects have None for unspecified attributes.
The best way to implement what you're after is to use namedtuple:
from collections import namedtuple
class SearchError(namedtuple('SearchError', 'severity message')):
def __new__(cls, severity=0, message=''):
return super(SearchError, cls).__new__(cls, severity, message)
The problem here is that slice objects default to having None values as attributes. So, a[:2] passes in slice(None,2,None). When you break this apart and try to pass it to xrange, you'll get a TypeError:
>>> xrange(None,2,None)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: an integer is required
Try a[0:2:1] and your code will work. Ultimately, you could do something like:
val.start = 0 if val.start is None else val.start
val.stop = 2 if val.stop is None else val.stop
val.stop = 2-val.stop if val.stop < 0 else val.stop
val.step = 1 if val.step is None else val.step
to unravel your slices into useable indices (In the general case, it'd be better to use len(self) instead of 2, but I don't know if your object has defined __len__.
Or, even better:
start,stop,step = val.indices(len(self))
Similarly, in the case where you do a[-1], you're not passing in a slice, a 0 or a 1, so you hit the else clause where you to raise an IndexError.
I mucked around the code and found the following solution.
It uses lists but to only store the names of the variables - Not the actual values. Additionally it also provides the method add to add a new variable with a given name and value. The new variable will also be indexable. (The add function is not needed by my class, but is nice to have around)
Thanks to #mgilson for nudging me in this direction
class SearchError(object):
def __init__(self,severity=0,message=''):
self.severity = severity
self.message = message
self._length = 2
self._vars_list = ['severity','message',]
def __getitem__(self,val):
if isinstance(val,slice):
steps = val.indices(self._length)
return [self.__getitem__(i) for i in xrange(*steps)]
elif val < 0:
i = self._length + val
if i < 0:
raise IndexError,"Index Out of range for SearchError object"
else:
return self.__getitem__(i)
else:
try:
return getattr(self,self._vars_list[val])
except IndexError:
raise IndexError,"Index Out of range for SearchError object"
def add(self,var_name,value):
self._vars_list.append(var_name)
self._length += 1
setattr(self,var_name,value)
The results
>>> a=SearchError(1,"Fatal Error")
>>> a[-1]
'Fatal Error'
>>> a[-2]
1
>>> a[-3]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 14, in __getitem__
IndexError: Index Out of range for SearchError object
>>> a[2]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 21, in __getitem__
IndexError: Index Out of range for SearchError object
>>> a[1]
'Fatal Error'
>>> a[0]
1
>>> a[:]
[1, 'Fatal Error']
>>> a.add('new_severity',8)
>>> a[:]
[1, 'Fatal Error', 8]
>>> a[3]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 21, in __getitem__
IndexError: Index Out of range for SearchError object
>>> a[2]
8
>>> a.new_severity
8
>>> a[:3]
[1, 'Fatal Error', 8]
>>> a[:4]
[1, 'Fatal Error', 8]
>>> a[:2]
[1, 'Fatal Error']
As far as I can see, you need lists (to either store the actual variables or their names). If someone has a better alternative please do post

Can I create function using 'function' class?

I would like to know, just for fun, if I can create functions using function class constructor, i.e. without language construct def, just like creating class by instantiating type object. I know, function constructor takes 2 args - code object and globals. But I don't know how I should compile the source properly.
>>> def f():
... pass
>>> Function = type(f)
>>> Function
<class 'function'>
>>> code = compile("x + 10", "<string>", "exec")
>>> f = Function(code, globals())
>>> f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
NameError: name 'x' is not defined
>>> f(20)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: <module>() takes 0 positional arguments but 1 was given
You need to set many attributes on the code object, such as co_varnames, co_nlocals, etc.
What clearly works is
code = compile("def foo(n):return n+10", "<string>", "exec").co_consts[0]
func = Function(code, globals())
but I guess this would be considered cheating. To really define the code object from scratch, do (for 3.3)
code = types.CodeType(1, 0, 1, 2, 67, b'|\x00\x00d\x01\x00\x17S', (None, 10),
(), ('x',), '<string>', 'f', 1, b'\x00\x01')
func = Function(code, globals())
print(func(10))
This, of course, requires you to do the entire compile() yourself.
Well, this works:
>>> x = 0
>>> def f(): pass
...
>>> func = type(f)
>>> code = compile("global x\nx += 10","<string>","exec")
>>> nf = func(code,globals())
>>> nf()
>>> x
10
Don't know how you'd pass arguments to the function though.

adding items to treeview in PyGObject

I have a GUI created in Glade, and I would like to populate the treeview widget. Here is the relevant part of my code
def __init__(self):
.....
self.fill_store()
self.add_column(self.widget('treeview_preview'))
self.widget('treeview_preview').set_pixbuf_column(0)
def fill_store(self):
self.widget('liststore_preview').clear()
foo = GdkPixbuf.Pixbuf.new_from_file('9.png')
da = Gtk.Image.new_from_pixbuf(foo)
self.widget('liststore_preview').append([da])
def add_column(self, treeview):
renderer = Gtk.CellRendererPixbuf()
column = Gtk.TreeViewColumn("Preview", renderer, pixbuf = 0)
column.set_sort_column_id(0)
treeview.append_column(column)
Yet, when I try to run the code, I get an error, which informs me that renderer is not defined. The offending line is
column = Gtk.TreeViewColumn("Preview", renderer, pixbuf = 0)
Can someone point out the error? In case it helps, here is the traceback
Traceback (most recent call last):
File "test.py", line 10, in <module>
class test:
File "test.py", line 48, in test
column = Gtk.TreeViewColumn("Preview", r, pixbuf = 0)
NameError: name 'r' is not defined
Thanks,
v923z
Are you sure you don't have an typo like this?
>>> something = 1
>>> somthing # typo, left out 'e'
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'somthing' is not defined

Categories

Resources