How to I declare a default value in a python object?
Without a python object it looks fine:
def obj(x={123:'a',456:'b'}):
return x
fb = obj()
print fb
With a python object I get the following error:
def foobar():
def __init__(self,x={123:'a',456:'b'}):
self.x = x
def getStuff(self,field):
return x[field]
fb = foobar()
print fb.x
Traceback (most recent call last):
File "testclass.py", line 9, in <module>
print fb.x
AttributeError: 'NoneType' object has no attribute 'x'
How do I get the object to return the value of a variable in the object?
With a python object, I got an error:
def foobar():
def __init__(self,x={123:'a',456:'b'}):
self.x = x
def getStuff(self,field):
return x[field]
fb2 = foobar({678:'c'})
print fb2.getStuff(678)
Traceback (most recent call last):
File "testclass.py", line 8, in <module>
fb2 = foobar({678:'c'})
TypeError: foobar() takes no arguments (1 given)
You didn't define a class, you defined a function with nested functions.
def foobar():
def __init__(self,x={123:'a',456:'b'}):
self.x = x
def getStuff(self,field):
return x[field]
Use class to define a class instead:
class foobar:
def __init__(self,x={123:'a',456:'b'}):
self.x = x
def getStuff(self, field):
return self.x[field]
Note that you need to refer to self.x in getStuff().
Demo:
>>> class foobar:
... def __init__(self,x={123:'a',456:'b'}):
... self.x = x
... def getStuff(self, field):
... return self.x[field]
...
>>> fb = foobar()
>>> print fb.x
{456: 'b', 123: 'a'}
Do note that using a mutable value for a function keyword argument default is generally not a good idea. Function arguments are defined once, and can lead to unexpected errors, as now all your classes share the same dictionary.
See "Least Astonishment" and the Mutable Default Argument.
to define a class in python you have to use
class classname(parentclass):
def __init__():
<insert code>
With your code you're declaring a method not a class
Use
class foobar:
instead of
def foobar():
Related
This question already has answers here:
Python: weird "NameError: name ... is not defined" in an 'exec' environment
(2 answers)
Closed 7 years ago.
You can define both classes and functions in exec'd code without problems:
my_func = """
def test_func():
print "Hi from test_func!"
"""
my_class = """
class test_class:
def __init__(self):
self.a = "a"
"""
def call_func():
exec(my_func)
test_func()
def call_class():
exec(my_class)
a = test_class()
>>> call_func()
Hi from test_func!
>>> call_class()
a
However, defining both a class and a function that uses that class in exec'd code results in a NameError, because the class doesn't end up in the correct scope:
my_class_fun = """
class test_class_2:
def __init__(self):
self.a = "a"
def test_func_2():
a = test_class_2()
print(a.a)
"""
def test_2():
exec(my_class_fun)
test_func_2()
>>> test_2()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in test_2
File "<string>", line 7, in test_func_2
NameError: global name 'test_class_2' is not defined
Passing globals() as the second argument to exec so that everything ends up in the global namespace fixes this problem.
My question is, why is that necessary? test_class_2 and test_func_2 seem like they should both be local to test_2, so why doesn't test_func_2 have access to test_class_2?
EDIT:
Fundamentally, my question is why is test_2() above different from something like this code, which works fine:
def test_func():
class test_class:
def __init__(self):
self.a = "a"
def test_func_inner():
c = test_class()
print(c.a)
test_func_inner()
>>> test_func()
a
Because your class (and function) not in global space
Demo:
>>> def test_2():
... exec(my_class_fun)
... global test_class_2
... global test_func_2
... test_func_2()
...
>>> test_2()
a
I made a constant decorated that looks like this
def constant(f):
def fset(self, value):
raise TypeError
#wraps(f)
def fget(self):
return f()
return property(fget, fset)
but when I use it on a function and call it, I get thrown a type error for not passing in enough arguments, I thought adding in the wraps decorator would solve this but it didn't.
class IrrigationAmount(AbstractCalculation):
def __init__(self, wvf, fc):
self._wvf = float(wvf)
self._fc = float(fc)
self._value = 0
def calculate(self):
self._value = (self.fc*SECTORVOLUME - self.wvf*SECTORVOLUME)/FLOWRATE
#constant
def value(self):
return self._value
Here's how I tested it, I don't understand what I'm doing wrong, mainly why self isn't being passed in automatically due to the wraps. I probably misunderstood what wraps does terribly.
>>> from irrigationservice.irrigation import IrrigationAmount
>>> a = IrrigationAmount(0.12, 0.2)
>>> a.calculate()
>>> a.value
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/Users/krishna/Documents/irrigationwebserver/webserver/irrigationservice/utils.py", line 12, in fget
return f()
TypeError: value() takes exactly 1 argument (0 given)
I think you want to replace the constant function definition and the #constant decorator with something like this:
#property
def value(self):
"""return the protected value"""
return self._value
EDIT: add the following example to address some comments
Create file myvalue.py...
class MyValue:
def __init__(self, x, y):
self._x = x
self._y = y
self._value = 0
def calculate(self):
self._value = self._x*self._y
#property
def value(self):
"""return the protected value"""
return self._value
Now run in python:
>>> from myvalue import MyValue
>>> z = MyValue(2, 3)
>>> z.value
0
>>> z.calculate()
>>> z.value
6
>>> z.value = 10
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
While Steve's answer is the right way to do this (you don't need a special #constant decorator when #property is naturally read-only unless you explicitly decorate other methods with #propname.setter), the reason you have the problem is that the decorated class method isn't bound, and you're not explicitly passing self to it.
Change the code to:
def fget(self):
return f(self)
so the self argument actually goes where it's supposed to.
when I learn 'property' of python, To my surprise, the output is not as same as expected.The code illustrated below:
class HideX(object):
def __init__(self,x):
self.x = x
def get_x(self):
return ~self.__x
def set_x(self,x):
assert isinstance(x,int),\
'"x" must be an integer!'
self.__x = ~x
x = property(get_x, set_x)
inst = HideX(20)
#inst.x = 20#
when it executes inst = HideX(20). I think it will call __init__(self,x) so the instruction self.x = xwill be executed. The problem occurs. I think it will not call x = property(get_x, set_x)because self.x is in the body of class (it is in the top of the class).I've always thought
only in the outside of class (as show in #..#)can we access x = property(get_x, set_x) am I wrong? can you understand what I mean?
sovled:
After repeated tests, I found amazedly that when we executeinst = HideX(20), the code x = property(get_x, set_x)
will be called in the first place ,not the 'init(self,x)'.Totally beyond my expectation!!!(In the java ,when we create an instance,the init() of the class will be first called i think ,maybe i am wrong)
(1)Can you give me an explanation of the intrinsic mechanism? I am a green hand,Thanks for your patience.
the code below is the Segment I copy from :
class HideXX(object):
def __init__(self, x):
self.x = x
#property
def x():
def fget(self):
return ~self.__x
def fset(self,x):
assert isinstance(x,int),\
'"x" must be an integer!'
self.__x = ~x
return locals()
#x = property(**x())
inst = HideXX(1)
But it can not run correctly
the error code is :
File "<string>", line 21, in <module>
File "<string>", line 4, in __init__
AttributeError: can't set attribute
(2)Is the book wrong ?? When I removed #property and add the code 'x = property(**x())' It works!!!
can you explain the reason for me ? thanks very much
For your first question , the answer is simple, x is an attribute of the class (not the object/instance of the class) , it would be evaluated when the class gets defined (not when its object is created).
An Example to show this -
>>> class CA:
... y = print("Hello")
... def __init__(self):
... print("Blah")
...
Hello
>>> c = CA()
Blah
As you can see the value of y gets calculated when the class is defined, its the same with all functions in the class, they get defined when the class gets defined, but they are evaluated only when the function gets called.
Also, using the #property is not same as property(**x()) , when you do the later , **x() resolves to -
{'fget': <function HideXX.x.<locals>.fget at 0x00943B28>, 'fset': <function HideXX.x.<locals>.fset at 0x00943CD8>}
And then these positional arguments are used for setting the getter and setter for the property x , whereas the #property annotation is used to define the getter for property x.
I've written a program in which I have a fairly typical class. In this class I create multiple namedtuple objects. The namedtuple objects hold many items, which all work fine, except for lambda functions that I try to bind to it. Below is a stripped down example and the error message that I am receiving. Hope someone knows why this is going wrong. Thanks in advance!
FILE: test.py
from equations import *
from collections import namedtuple
class Test:
def __init__(self, nr):
self.obj = self.create(nr)
print self.obj.name
print self.obj.f1(2)
def create(self, nr):
obj = namedtuple("struct", "name f1 f2")
obj.name = str(nr)
(obj.f1, obj.f2) = get_func(nr)
return obj
test = Test(1)
FILE: equations.py
def get_func(nr):
return (lambda x: test1(x), lambda x: test2(x))
def test1(x):
return (x/1)
def test2(x):
return (x/2)
ERROR:
Traceback (most recent call last):
File "test.py", line 17, in <module>
test = Test(1)
File "test.py", line 8, in __init__
print self.obj.f1(2)
TypeError: unbound method <lambda>() must be called with struct instance as first argument (got int instance instead)`
The namedtuple() constructor returns a class, not an instance itself. You are adding methods to that class. As such, your lambda's must accept a self argument.
In any case, you should create instances of the named tuple class you created. If you don't want to give your lambdas a self first argument, adding them to the instance you then created would work fine:
from equations import *
from collections import namedtuple
Struct = namedtuple("struct", "name f1 f2")
class Test:
def __init__(self, nr):
self.obj = self.create(nr)
print self.obj.name
print self.obj.f1(2)
def create(self, nr):
obj = Struct(str(nr), *get_func(nr))
return obj
test = Test(1)
I have a method (__init__) in a class, and I want to use a function from the class in this method.
But when I want to run my program. I get: NameError: global name 'myfunction' is not defined
Someone, who knows what I have to do? :)
Thank you. But I have still a problem, because def myFunc(self, a): is a method and I wanted a function.
class Myclass(object):
def __init__(self, a):
self.a = self.myFunc(a)
def myFunc(self, a):
return a+1
Then you don't have a function call in the method, but you have a method call in it.
When creating a class you must specify the object when calling its methods:
>>> class A(object):
... def __init__(self, val):
... self.val = self._process(val)
... def _process(self, val):
... return val % 7
... process = _process #if you are outside methods then you don't
... #have to add "self.".
...
>>> a = A(5)
>>> a.process(3)
3
>>> a._process(6) #"a" is passed as the "self" parameter
6
As you can see in a class definition, but outside the methods you must specify the method name only, and not the "self.". Also you can't refer to a method not already defined:
>>> class B(object):
... def __init__(self):pass
... def method1(self):pass
... __call__ = method2 #method2 not defined!
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 4, in B
NameError: name 'method2' is not defined