Class variable query in python - python

Framework: Robot, Language: Python-3.7.1 Proficiency: Novice
I have a variable args=[] defined at class level. The values of the variables are being assigned from command prompt using module 'sys'
import sys
class Runner():
args = []
def argument_reader(self):
self.args = list(sys.argv)
def login(self):
return self.args[1], self.args[2]
I could print all the values of args as long as execution stays within the module. If I wanted to call the same values from other module, it does not return anything as the values are being cleared out from the memory. Since class variables are static by default in python, why system is not RETAINING the values?
cmd line>>py Runner.py testing test#123
For Example:
Calling method from same class:-
run = Runner()
run.argument_reader()
print(run.login())
Output>>> testing, testing#123
Calling the same method from another class:-
runn = Runner.Runner()
print(runn.login())
output>> IndexError: list index out of range

If you want a singleton-type value, change your code to look like this.
class Runner():
args = []
def argument_reader(self):
Runner.args = list(sys.argv)
def login(self):
return Runner.args[1], Runner.args[2]
Otherwise, you'll have to call argument_reader() on each instance.

Related

Self variable not updated after running function in different class

I have a class (AngleInfo) in a file (Display.py) with a self variable (WheelAngle) which is not updated after running a function (GetAngle). This function is being called in a class in a second file (ManageInfo.py) with a trigger based on events. When I try to use the WheelAngle in a second class (AngleProcess) in Display.py, the value doesn't update from the initialization. When the function is triggered in the MessageHandler class, it has access to raw data being represented by m in the GetAngle declaration.
There is another class (SpeedInfo) in a different file (Radar.py) where the self variable (VehicleSpeed) is being updated after running its corresponding information retrieval function (GetSpeed) in the ManageInfo class.
The working case has a threading system, but after replicating it in the non-working case I found no improvement. I don't understand why the WheelAngle is not being updated inside the class and comparing with the working case hasn't brought me closer to the answer.
So basically after I run GetAngle I see WheelAngle has the correct value inside that function but when I call the self variable in the UpdatePlot function of the AngleProcess class in the Display.py file I get the initial value. I even tried to create a different function in the AngleInfo class to access WheelAngle and then call this function in the UpdatePlot function in the AngleProcess class, but the result is the same.
Keep in mind a working example is not possible since it requires live data being sent. Also, even though WheelAngle and VehSpeed don't seem to be used, the code that follows has been ommited for simplicity!
Any ideas? There is a sample of the code below. Thank you!
Display.py
class AngleInfo():
def __init__(self):
self.WheelAngle = 0
def GetAngle(self,m):
self.WheelAngle = float(m) # Angle is correct
class AngleProcess():
def __init__(self):
self.AngleInfoObj = AngleInfo()
def UpdatePlot(self,tupledata):
WheelAngle = self.AngleInfoObj.WheelAngle # Angle is set to initial
Radar.py
class SpeedInfo(threading.Thread):
def __init__(self,page):
threading.Thread.__init__(self)
self.daemon = True
self.start()
self.VehSpeed = 0
def run(self):
VehSpeed = self.VehSpeed # Speed is correct
def GetSpeed(self,m):
self.VehSpeed = float(m) # Speed is correct
ManageInfo.py
from AurixCAN import Receiver
from Radar import SpeedInfo
from Display import AngleInfo
class MessageHandler:
def __init__(self,page):
self.SpeedInfo = SpeedInfo(page)
self.AngleInfo = AngleInfo()
DataSet = Receiver(canIDsandCalls={0xE:[self.SpeedInfo.GetSpeed,self.AngleInfo.GetAngle]})

Call a Function by alias in a Decorator

The current code I have, allows the function to call the wrapper decorator, and uses the function name in its code. However, I'm looking for a way to give the function a 'alias' in a way as an argument. Here's the current code:
import os, sys
# Take user input
message = input('type command: ')
# Command wrapper
ALLCOMMANDS = {}
def command(function):
ALLCOMMANDS[function.__name__] = function
return function
# Commands
#command
def foo():
print("bar")
#command
def goo():
print('ber')
# Run appropriate command
if message in ALLCOMMANDS:
ALLCOMMANDS[message]()
For example I would want to be able to call the function by a name such as '!foo' from the user input, so maybe the argument would look like #command(name='!foo'), I just don't know where to go from there to use that argument in the decorator since it already has an argument.
I attempted
# Command wrapper
ALLCOMMANDS = {}
def command(name):
ALLCOMMANDS[name] = name
return name
but keep getting errors and I assume I am missing something
You should read up a bit more on python decorators. You're getting an error with:
def command(name):
ALLCOMMANDS[name] = name
return name
Because of the return name.
Decorators are just syntactic sugar. This:
#command
def foo():
print('bar')
Is equivalent to:
def foo():
print('bar')
foo = command(foo)
From this you can see why your original decorator works. At the end you return function.
Things get a little tricker when you have a decorator that takes arguments. Desugared the following:
#command('nickname')
def foo():
print('bar')
Looks like this:
def foo():
print('bar')
foo = command('nickname')(foo)
So, to write a decorator that takes arguments, the decorator needs to return a function that takes the function to decorate as an argument:
def command(nickname):
def wrapped(f):
ALLCOMMANDS[nickname] = f
return f
return wrapped
Also consider making ALLCOMMANDS an attribute on your command instead of a global (UPPER_SNAKE is usually reserved for constants):
def command(nickname):
def wrapped(f):
command._functions[nickname] = f
return f
return wrapped
command._functions = {}

Python, main method not running (multiple classes in same file)

Context:
I developed a python script to be run on a remote linux server. Running using Python 3.6.1. The script worked but was very messy, and procedurally written as opposed to OO. So, I re-wrote this script into 2 different classes. One main class and a blueprint class for objects.
My script is a lot more complicated, i just simplified it for this question.
Desired Function:
Read values from CSV file. Create Objects from these values, 1 object per line. Do some calculations on the values on init'ing the object (in the objects class). Have these objects be accessible from the main class (Base class).
Problems:
I need some clarification on:
The main method is not running. Tried variants on the method call, like Base.main(), including the "if name" statement inside the Base class, and it complains about self not being defined
The "self" reference. Are my usages of this correct? For example: Adding the attribute "age" into the Person objects so you can access it with person.age for example. My method call "self.input_file_handling(Base.inputFilePath)" etc.
Script:
import csv
class Person:
def calculate_age(self):
self.age = 2017 - self.birthYear
def __init__(self, name, birthYear):
self.name = self.strip_characters(self, name)
self.birthYear = int(birthYear)
self.calculate_age()
class Base:
inputFilePath = "input.csv"
people = []
def main():
self.input_file_handling(Base.inputFilePath)
#More methods here
#staticmethod
def input_file_handling(input_file_path):
input_file_path = str(input_file_path)
with open(input_file_path, 'r') as csv_file:
csv_reader = csv.DictReader(csv_file)
for line in csv_reader:
name = line['Name']
age = line['age']
person = Person(name, age)
people.append(person)
if __name__ == '__main__':
main()
First the main method of Base class is not static because it use the self variable, so is necessary receive that.
If you want call the main method and use the self variable you need make something like that:
class Base:
def main(self):
pass
if __name__ == '__main__':
instance_of_base = Base()
instance_of_base.main()
You can call the input_file_handling method without using self, because it's static
Base.input_file_handling(Base.inputFilePath)
I think you need learn more about how python resolve static things and the class and object variables.
Python is not C. There is no main function that automagically executes.
The main method that you defined is inside Base class, but it doesn't accept an argument for the instance.
Either modify it so it accept it (ie self by the convention) or make it a static method.
Then in if __name__ == '__main__': either use Base().main() or Base.main(), depending on what approach you decided to take.
But you don't seem to need any of this, and only doing it for the sake of forcing Python to look/work as other languages (looking at you C++/Java). Python doesn't require you to have a class or a 'main' function/method to execute code.
Your code written in a Pythonic way would be: (Python3)
import csv
from time import time, gmtime
INPUT_FILE_PATH = "input.csv"
class Person:
def __init__(self, name, birth_year):
self.name = name.strip()
self.birth_year = birth_year
#property
def birth_year(self):
return self._birth_year
#setter.birth_year
def birth_year(self, value):
self._birth_year = value
self._age = gmtime(time()).tm_year - value
#property
def age(self):
return self._age
#setter.age
def age(self, value):
self._birth_year = gmtime(time()).tm_year - value
self._age = value
def input_file_handling(input_file_path):
people = []
with open(input_file_path, 'r') as csv_file:
csv_reader = csv.DictReader(csv_file)
for line in csv_reader:
people.append(Person(line['Name'], int(line['age'])))
return people
if __name__ == '__main__':
people = input_file_handling(INPUT_FILE_PATH)
You seem to come from a OOP-only language (C# maybe?).
Some tips:
Avoid globals when able for variables, use them for function definition, class definition and constants.
Do not use a new class to store functions that do not require it
Use lower case and '' for variable and function names, Use CamelCase for class names, use caps and '' for constants.
Use duck typing: do not check that a argument is of a given type, try to use it as if it was and handle throw exceptions if it isn't.
Properties ar your friends if you want to force a specific bahaviour at getting or setting a class attributes
If you do not understand somehting ask in the comments.

Dictionary of functions for all function in class

I'm relatively new to python and I have a class that has a bunch of different function. I read in the user input and depending on the user input I call a different function. Instead of having a bunch of if else statements I thought it would be better to have a dictionary of functions so currently my class looks like this:
class Foo:
def func1(self):
#do something
def func2(self, arg1):
#do something else
def func3(self, arg1, arg2):
#do something
def func4(self, arg1):
#do something
def __init__(self):
self.functions = {"FUNC2": func2, "FUNC4":func4}
def run_loop(self):
while 1:
user_input = raw_input()
cmd = user_input.split(' ')[0]
if cmd in self.functions:
self.functions[cmd].__get__(self, type(self))()
else:
#call other functions
I'm calling this in a main.py like so:
c = Class()
c.run_loop()
My issue is that I'm getting the following error NameError: global name 'func2' is not defined`. I'm not really sure why this is happening. I get the error in the constructor. Any ideas?
You need to specify that the function is within the class by adding self before it.
def __init__(self):
self.functions = {"FUNC2": self.func2, "FUNC4":self.func4}
You need to use self to access class functions from other function in same class. The corrected code will be
self.functions = {"FUNC2": self.func2, "FUNC4":self.func4}
The function is not identified within the class. Function "func2" & "func4" are part of the class and can be referred using the self...

Dynamically call a method from a list of Python classes/objects

I have X number of python classes that all inherit from the same abstract base class, which expects children to implement a single method called executeTest()
Class TestCase:
def executeTest():
#do some logic for the test, then return if it passed or failed
In my main program I need to load an instance of each class that inherits this base class one at a time, call executeTest(), and record the result into some sort of collection for later use. The number of classes that implement TestCase will continue to grow over time, as people think up new tests to write.
How can I do this efficiently in python? Do I need to have a separate XML or similar type file which has a list of all individual class names, and then use some sort of class loading function inside a for loop? This is my first night coding in python so I'm not even really sure what techniques or keywords to search for.
This is a meta answer - which means that I think that you should think about your design calling tests.
In python there are well established ways to write tests. [1]
And there are also tools which collect all the available tests and executes them (including stats, coverage, xml output, ...). [2]
If I were you I would have a look at them. If you can use them, there is no need to re-invent the wheel.
[1] http://docs.python.org/library/unittest.html
[2] http://readthedocs.org/docs/nose/en/latest/
Use a decorator to enumerate the classes, and execute the methods with a list comprehension.
I will try to do it this way:
1) Save your abstract class in test_case.py
class TestCase:
def executeTest():
#do some logic for the test, then return if it passed or failed
2) Save all your child classes in in test_case_children.py
from test_case import TestCase
class Test_Case_1(TestCase):
def executeTest():
#overriden function
class Test_Case_2(TestCase):
def executeTest():
#overriden function
class Test_Case_3(TestCase):
def executeTest():
#overriden function
3) Save main function in main.py:
from test_case import TestCase
import test_case_children
def main():
#grab the all the elements in the script 'test_case_children'
items = test_case_children.__dict__
#build list of all 'TestCase' sub-classes
test_classes = []
for (key, value) in items.items():
try:
# check whether the item is a sub-class of 'TestCase' class
if TestCase.__subclasscheck__(value):
test_classes.append(value)
except TypeError: #if item is not of type 'TestCase', ignore it
pass
#run the tests
for test_class in test_classes:
test_runner = test_class()
test_runner.executeTest()
# this will run main() method, only when script is directly executed
# from shell or command prompt ...
if __name__ == "__main__":
main()
4) Execute the main.py script:
$ python main.py
Note: One more thing, the folder in which you will save these files should also contain an empty __init__.py file to make that folder as python app(something like packages in Java or namespaces in C++). If you don't then those import statements will not work, probably.
[ Update for running test_cases from different files ]
1) Keep the files in following heirarchy:
<root>/
------>test_case/
---------------->__init__.py
---------------->main.py
---------------->test_case.py
---------------->test_case_children/
--------------------------------->__init__.py
--------------------------------->test_case_1.py
--------------------------------->test_case_2.py
--------------------------------->test_case_3.py
2) Save your abstract class in test_case/test_case.py
class TestCase:
def executeTest():
#do some logic for the test, then return if it passed or failed
3) Save sub-classes like this:
File: test_case/test_case_children/test_case_1.py
from test_case.test_case import TestCase
class Test_Case_1(TestCase):
def executeTest():
#overriden function
File: test_case/test_case_children/test_case_2.py
from test_case.test_case import TestCase
class Test_Case_2(TestCase):
def executeTest():
#overriden function
File: test_case/test_case_children/test_case_3.py
from test_case.test_case import TestCase
class Test_Case_3(TestCase):
def executeTest():
#overriden function
4) Save main function in main.py:
from test_case import TestCase
from test_case import test_case_children
def main():
#grab the all the elements in the module 'test_case_children'
items = test_case_children.__dict__
#build list of all 'TestCase' sub-classes
test_classes = []
for (dict_key, dict_value) in items:
#check whether the type of item's value is a module,
# if its a module it's likely to contain a TestCase subclass...
if str(type(dict_value)) == "<type 'module'>":
for (key, value) in dict_value.items():
try:
# check whether the item is a sub-class of 'TestCase' class
if TestCase.__subclasscheck__(value):
test_classes.append(value)
except TypeError: #if item is not of type 'TestCase', ignore it
pass
#run the tests
for test_class in test_classes:
test_runner = test_class()
test_runner.executeTest()
# this will run main() method, only when script is directly executed
# from shell or command prompt ...
if __name__ == "__main__":
main()
5) Execute the main.py script:
$ cd test_case/
$ python main.py
I hope this would work for you.

Categories

Resources