Changing global objects while still being able to validate arguments - python

Currently I have 2 global variables within my python module. I wanted to get away from using the global variable scope, while still being able to call the 2 variables throughout my module. Basically what's the best way to get away from the global object, while still being able to validate arguments.
I tried creating a class within a function, which i realized wouldnt work.
global gl_args
global gl_hashType
gl_args 1⁄4 parser.parse_args()
if gl_args.md5:
gl_hashType = 'MD5'
elif gl_args.sha256:
gl_hashType = 'SHA256'
elif gl_args.sha512:
gl_hashType = 'SHA512'
elif gl_args.sha224:
gl_hashType = 'SHA224'
elif gl_args.sha384:
gl_hashType = 'SHA384'
else:
gl_hashType = "Unknown"
logging.error('Unknown Hash Type Specified')
DisplayMessage("Command line processed: Successfully")
return
this is only one piece of where it is used but the 2 variables are used throughout the program.
Calling the variable throughout the module.

Sounds like you want a class
class MyClass(object):
def __init__(self,x,y):
self.x = x
self.y = y
def f1(self):
return self.x + self.y
def f2(self):
return self.y - self.x
def area(self):
return self.y*self.x
used like this:
my_instance = MyClass(4,5)
my_instance.f1()
my_instance.f2()

Related

Is it possible store return value of one function as Global Variable?

I Have function register a patient that will Return Medical record Number , Need store this as Global Variable to so that use the same for Different Functions Eg: Create Vital Sign , Create Lab Order etc.
aqTestCase.Begin(" User able to Register a Unknown patient")
Log.AppendFolder("Unknown Registeration Logs")
ERPage=Aliases.MedBrowser.pageER
ReusableFunctions.ClickonObject(ERPage.RegisterUnknownPatientIcon)
ReusableFunctions.ClickonObject(ERPage.UnknownRegMaleLabel)
ReusableFunctions.setTextValue(ERPage.txtAge, "20")
ReusableFunctions.ClickonObject(ERPage.UnknownRegregistrBtn)
ReusableFunctions.ClickonButton(ERPage.AssignBuutonclose)
AppReusableFunctions.getToastMsgs(ERPage)
labelER = Aliases.VidaPlusBrowser.pageER.FindElement("//span[.='ER']")
ReusableFunctions.ClickonObject(labelER)
mrn = ERPage.FindElement("//div[10]/div[5]/app-er-patient-grid-mrn/span").contentText
aqUtils.Delay(2000)
ReusableFunctions.ClickonObject(ERPage.ERArrvialTime)
Log.Message(" Unknown Patient Registred MRN is : " +mrn)
return mrn
You can set the variable as a global variable and return it.
def foo():
global X
X = 1
return X
In your case, creating a class may work better.
class Foo:
def __init__(self, x):
self.x = x
def bar(self):
return self.x
f = Foo(1)
f.bar()
x = "awesome"
def myfunc():
global x
x = "fantastic"
myfunc()
print("Python is " + x)

How do I get python to read that () is 0?

I'm having issues trying to pass an empty parameter can someone explain to me why my code isn't working. I have a math test file that goes through my math library file but my lib file can't read the () code. When I run the code it says init() missing 1 required positional argument: 'y'
import MathLib as math
math test:
if __name__ == '__main__':
math_obj1 = math.MyMathLib(2.0)
math_obj2 = math.MyMathLib(-0.5)
math_obj3 = math.MyMathLib() # this should give 0.0
print("Math obj1 value = ",math_obj1.get_curr_value() )
print("Math obj2 value = ",math_obj2.get_curr_value() )
print("Math obj3 value = ",math_obj3.get_curr_value() )
import math
class MyMathLib:
def __init__(self, y,):
self.y = y
if self == None:
value == 0.0
As posted, your definition of the __init__() function has y as a required argument.
If you want it to be optional and have a default value of zero, then write it this way:
class MyMathLib:
def __init__(self, y=0.0):
The self variable isn't actually a passable parameter in class methods (I recommend you take another look at python classes). The first (and only) passable parameter in your init function is y. Since y has no default variable, you must pass a value for y, or give it a default value:
def __init__(self, y=0.0):
self.y = y
Also I'm not sure what you're trying to achieve with this line, it makes no sense:
if self == None:
value == 0.0
value is only local to the init function, maybe you meant self.value? Even then, self will never be None (unless you assign self = None within the method), so the statement will never trigger. Ontop of that, you've used a double == instead of =.
You have to set default value in __init__
def __init__(self, y=0.0):
self.y = y
and then you don't have to check None
Or using None
def __init__(self, y=None):
self.y = y
if self.y is None:
self.y = 0.0
It can be useful if you want to recognize if someone used MyMathLib() or MyMathLib(0.0)
That is because your __init__ requires two arguments instead of one. Instead of doing this, you can pass a default variable like #Jay Mody's answer. And also:
self == None will never be true because self always passes in a value y.
Here is another way you can do it:
class MyMathLib:
def __init__(self):
self.y = 0.0
def passNumber(y):
self.y = y
As you can see, if the number is passed using passNumber, that means that the number isn't 0.0. This is another way to do it.

Access class variables with same function

I want to create a function within a class that can access two different members with the same function. For example in the code below, I want both of the lines below to use the 'apply' function on different variables in the class
print(state.apply(rate))
print(state.apply(wage))
I had thought if I put in a dummy variable in the function definition (called exposure), it would replace it with the variables passed to the function (rate and wage in the example below). What is the correct way of doing this in python 3?
class State():
def __init__(self):
self.rate = 0
self.wage = 0
def apply(self, exposure):
self.exposure = self.exposure - 1
return self.exposure
state = State()
rate = State.rate
wage = State.wage
print(state.apply(rate))
print(state.apply(wage))
EDIT: I had made a typo where I had State instead of state in each print statement. I have now corrected this
This would be the only way:
class State:
def __init__ (self):
self.rate = 0
self.wage = 0
def apply (self, exposure):
setattr(self, exposure, getattr(self, exposure) - 1)
return getattr(self, exposure)
>>> state = State()
>>> print(state.apply('rate'))
-1
>>> print(state.apply('wage'))
-1
>>> print(state.apply('wage'))
-2
Note that those are instance variables, so you cannot access them using the type, State, but only using the object, state.
However, I would say, that whatever you are trying, you’re doing it wrong. If you describe your actual problem, we may be able to suggest a way better solution for it instead.

Printing from within properties

I'm trying to make a robotics kit. Its designed to be simple so I'm using properties so when the users change a parameter the property method sends the serial command which controls motors/ servos/whatever.
This is the code at the moment, directly from a previous question I asked on here.
class Servo(object):
def __init__(self, which_servo, angle = 0):
self._angle = angle;
self._servo_no = which_servo
def get_angle(self):
return self._angle
def set_angle(self, value):
self._angle = value
print "replace this print statement with the code to set servo, notice that this method knows the servo number AND the desired value"
def del_angle(self):
del self._angle
angle = property(get_angle, set_angle, del_angle, "I'm the 'angle' property.
this is then initialized as such:
class robot(object):
def __init___(self):
self.servos = [Servo(0), Servo(1), Servo(2), Servo(3)]
Now, this works in the respect that it does change the variable through the getter and setter functions, however the prints in the getter and setter never is printed, thus if I replace it with a serial command I assume it won't do anything either, can anyone shed any light on this?
Thanks
Update: Thanks for the help using the servo file this is whats happened, there are three scenarios the first works and by extension I would have assumed the next two preferable scenarios would work but they don't any ideas?
This works
import servo
class Robot(object):
def __init__(self):
self.servos = [servo.Servo(0, 0), servo.Servo(1,0), servo.Servo(2,0)]
R = Robot()
R.servos[1].angle = 25
This does not:
import servo
class Robot(object):
def __init__(self):
self.servos = [servo.Servo(0, 0), servo.Servo(1,0), servo.Servo(2,0)]
R = Robot()
left_servo = R.servos[1].angle
left_servo = 25
Neither does this
import servo
class Robot(object):
def __init__(self):
self.servos = [servo.Servo(0, 0).angle, servo.Servo(1,0).angle, servo.Servo(2,0).angle]
R = Robot()
R.servo[1] = 25
Using the preferred decorator syntax for properties, this works fine. It'll also help you avoid issues like this in the future
class Servo(object):
def __init__(self, which_servo, angle = 0):
self._angle = angle;
self._servo_no = which_servo
#property
def angle(self):
return self._angle
#angle.setter
def angle(self, value):
self._angle = value
print "replace this print statement with the code to set servo"
#angle.deleter
def angle(self):
del self._angle
Seeing as your indentation is off here, I believe this is likely an issue of indentation in your source. This should work as well if you really want to use the old property function:
class Servo(object):
def __init__(self, which_servo, angle = 0):
self._angle = angle;
self._servo_no = which_servo
def get_angle(self):
return self._angle
def set_angle(self, value):
self._angle = value
print "replace this print statement with the code to set servo"
def del_angle(self):
del self._angle
angle = property(get_angle, set_angle, del_angle,"I'm the 'angle' property.")
Both of these work successfully for me (inside a file called servo.py)
>>> import servo
>>> s = servo.Servo(1, 2)
>>> s.angle
2
>>> s.angle = 3
replace this print statement with the code to set servo
EDIT
To address your new issues. When you assign R.servos[1].angle to left_servo, its not creating a reference to the servos angle, it's just setting left_servo to whatever the angle is. When you reassign 25 to it, you're not assigning to the angle you're assigning to the left_servo.
On the second one, I'm assuming you meant R.servos and not R.servo which should be raising an AttributeError. But the real problem as I see it, is you should be saying R.servos[1].angle = 25 and you're omitting the .angle.
To (attempt to) put it simply: When you use the = operator, you are changing where a name refers to, not what it refers to.
>>> x = 1
>>> x = 2
the second assignment does not overwrite the 1 in memory with a 2, it just changes where x refers to. So if I did something like
>>> x = 1
>>> y = x
>>> y = 2
>>> print x
1
the output is 1 because your are telling y to refer to the same place that x refers. Changing y to 2 changes where y refers to, it does not change the 1 already in memory.

Get the return value from a function in a class in Python

I am trying to simply get the value out of my class using a simple function with a return value, I'm sure its a trivial error, but im pretty new to python
I have a simply class set up like this:
class score():
#initialize the score info
def __init__(self):
self.score = 0
self.num_enemies = 5
self.num_lives = 3
# Score Info
def setScore(num):
self.score = num
# Enemy Info
def getEnemies():
return self.num_enemies
# Lives Info
def getLives():
return self.getLives
etc.....
Than I create an instance of the class as such:
scoreObj = score()
for enemies in range(0, scoreObj.getEnemies):
enemy_sprite.add(enemy())
I get the error saying that an integer is expected, but it got an instancemethod
What is the correct way to get this information?
Thanks!
scoreObj.getEnemies is a reference to the method. If you want to call it you need parentheses: scoreObj.getEnemies().
You should think about why you are using a method for this instead of just reading self.num_enemies directly. There is no need for trivial getter/setter methods like this in Python.
The first parameter for a member function in python is a reference back to the Object.
Traditionally you call it "self", but no matter what you call the first parameter, it refers back to the "self" object:
Anytime I get weird errors about the type of a parameter in python, I check to see if I forgot the self param. Been bit by this bug a few times.
class score():
#initialize the score info
def __init__(self):
self.score = 0
self.num_enemies = 5
self.num_lives = 3
# Score Info
def setScore(self, num):
self.score = num
# Enemy Info
def getEnemies(self):
return self.num_enemies
# Lives Info
def getLives(foo): #foo is still the same object as self!!
return foo.num_lives
#Works but don't do this because it is confusing
This code works:
class score():
def __init__(self):
self.score = 0
self.num_enemies = 5
self.num_lives = 3
def setScore(self, num):
self.score = num
def getEnemies(self):
return self.num_enemies
def getLives(self):
return self.getLives
scoreObj = score()
for enemy_num in range(0, scoreObj.getEnemies()):
print enemy_num
# I don't know what enemy_sprite is, but
# I commented it out and just print the enemy_num result.
# enemy_sprite.add(enemy())
Lesson Learned:
Class functions must always take one parameter, self.
That's because when you call a function within the class, you always call it with the class name as the calling object, such as:
scoreObj = score()
scoreObj.getEnemies()
Where x is the class object, which will be passed to getEnemies() as the root object, meaning the first parameter sent to the class.
Secondly, when calling functions within a class (or at all), always end with () since that's the definition of calling something in Python.
Then, ask yourself, "Why am I not fetching 'scoreObj.num_lives' just like so instead? Am I saving processing power?" Do as you choose, but it would go faster if you get the values directly from the class object, unless you want to calculate stuff at the same time. Then your logic makes perfect sense!
You made a simple mistake:
scoreObj.getEnemies()
getEnemies is a function, so call it like any other function scoreObj.getEnemies()

Categories

Resources