Function not working properly inside a class instance [duplicate] - python

This question already has answers here:
How to change a module variable from another module?
(3 answers)
Closed last year.
I have this module which stores a class, an instance of that class, a counter, and a dictionary:
#test_module.py:
class TestClass:
def __init__(self, name='name', attr='attr'):
self.name = name
self.attr = attr
def func(self, test_list):
test_dict[count] = test_list[-1].name + '_' + test_list[-1].attr
test_inst = TestClass()
count = 0
test_dict = {}
What I want is for the dictionary to store each consecutive value of the counter (1,2,3...) as a key and the name and attribute of the last class instance in a test_list. (All the code here is simplified for the sake of reproducing the problem, the actual number of classes and instances is greater).
In a notebook, I have the following code:
from test_module import *
test_list = []
test_list.append(test_inst)
count += 1
test_list_item = test_list[-1]
test_dict[count] = test_list_item.name + '_' + test_list_item.attr
test_list.append(test_inst)
count += 1
test_list_item = test_list[-1]
test_list_item.func(test_list)
What now is in the dictionary is:
{1: 'name_attr', 0: 'name_attr'}
Why am I getting zero as the second key?
I've tried specifying the count and the test_dict as global variables in the TestClass definition, but to no avail.
All works OK if I copy the contents of the test_module into the notebook, but this is not what I'm after. My goal is to have as much code as possible in the test_module. What am I doing wrong? How can I make it work properly?

I just copied your code and the output is
{1: 'name_attr', 2: 'name_attr'}

Related

How to get class instance variables, python

I would like to get the names of __init__ parameters and modify them when the code runs. My class looks like this:
class Sample:
def __init__ (self,indicators:dict):
self.names = []
self.returns = 0.0
for k,v in indicators.items():
setattr(self, k, v)
self.names.append(k)
The input of this class is a random choice of items from a lis; then I assign those random items to a dictionary with integer values.
indicatorsList =["SMA", "WMA", "EMA", "STOCHASTIC", "MACD", "HIGHEST_HIGH",
"HIGHEST_LOW", "HIGHEST_CLOSE", "LOWEST_HIGH", "LOWEST_LOW",
"LOWEST_CLOSE", "ATR", "LINGRES", "RSI", "WRSI", "ROC",
"DAY", "MONTH"]
# initializing the value of n
n = random.randint(2,int(math.ceil(len(indicatorsList)/2)))
randomIndList = n * [None]
for i in range(n):
choice = random.choice(indicatorsList)
randomIndList[i] = choice
...
...
sample = Sample(randDict)
Problem is, I don't know the names of these parameters in __init__, and I need to modify them later, for example like this:
sample.sma = random.randint(0, maxVal)
But I don't know if the object will have sma, or ema, or any other attribute, because of the way they're assigned randomly.
First of all, this code:
sample.sma = random.randint(0, maxVal)
will work, even if sample doesn't have an sma attribute. It will create one. Try it yourself and see.
But as you specified in your comment that you only want to modify attributes that already exist, that won't help in this case.
What you could do, with your existing class definition, is to loop over the names attribute you've already defined.
for name in sample.names:
setattr(sample, name, random.randint(0, maxVal))
However, you've basically reinvented a dictionary here, so why not redefine your class to directly use a dictionary?
class Sample:
def __init__(self, indicators:dict):
self.indicators = indicators
Now you no longer need dynamic setattr or getattr lookups. They're simply keys and values:
for key in sample.indicators:
sample.indicators[key] = random.randint(0, maxVal)
(This also means you don't need the separate names attribute.)

How to dynamically create instance of a class automatically in python [duplicate]

This question already has answers here:
How do I create variable variables?
(17 answers)
Closed 2 years ago.
I have a class and I want to create dynamically instances of that class. I don't know the exact number of instances so that I dont want to create that classes by a known variable like this:
class Person:
def __init__(self, age, gender):
self.age=age
self.gender=gender
P1=Person(23, "M")
P2=Person(64, "F")
P3=Person(12, "M")
I am looking for sth like
i=0
maxPopulation=10
while i< maxPopulation:
Person(randomx, randomy)
i+=1
But that way I don't know how to access the instances. During the runtime.
I am not looking for a random function.
Add them to a list.
i=0
maxPopulation=10
people = []
while i< maxPopulation:
people.append(Person(randomx, randomy))
i+=1
Or, cleaned up a bit to be more Pythonic:
maxPopulation=10
people = []
for _ in range(maxPopulation):
people.append(Person(randomx, randomy))
Or even more Pythonic:
max_population = 10
people = [Person(randomx, randomy) for _ in range(max_population)]

Python - Print list of objects in a table [duplicate]

This question already has answers here:
Printing Lists as Tabular Data
(20 answers)
Closed 9 years ago.
I have a class with several attributes:
class Fighter():
def __init__(self, name = "", gender = "", age = 0, weight = 0, win = 0, loss = 0, ko = 0, date = ""):
self.__name = name
self.__age = age
self.__weight = weight
self.__win = win
self.__loss = loss
self.__ko = ko
self.__date = date
From the user end of my program, an object is created and stored in a list using the following lines in a loop:
s = Fighter(name, gender, age, weight, wins, losses, ko, time)
collection.append(s)
I am able to sort this list by a number of attributes, such as name, weight, etc. and that works perfectly. I also have instance methods inside the class that return the value of a specific attribute, such as:
def fighter_age(self):
return str(self.__age)
My question is, how do I print this information as an organized table, with a column for each attribute, such as:
-----------------------------------------------------------------------
|Fighter Number|Name |Age |Weight |Wins|Losses|Date Added |
|1 |Anderson Silva|39 |185 |33 | 6 |2014-01-17 |
Check the duplicate link, and consider doing:
import sys
def prt_width(str, width):
sys.stdout.write('|' + str + ' '*(width-len(str)) + '|')
sys.stdout.flush()
for fighter in collection:
prt_width(fighter.number)
prt_width(fighter.name)
...
prt_width('\n')
Note: This would require you to calculate the maximun length of each field in advance (for instance, you need to loop through all names and determain the maximum length of a all names before submitting them for print, or just find a standard value that usually works). This is a manual approach, for some reason i tend to argue for going with manual approaches to learn stuff. Check the duplicate link for good libraries that does the thinking for you :)
If you wanted to be a bit clever about this, and use some of the functionality having a class gives you, you could store the width of the widest entry for each instance attribute as a class attribute:
class Fighter():
max_name_len = 4 # start with width of header 'Name'
...
def __init__(self, name, ...):
if len(name) > Fighter.max_name_len :
Fighter.max_name_len = len(name)
...
You can update these class attributes each time you create a new Fighter or change one of the their attributes (see property for how to wrap the attributes that might change with checking code). This saves you from needing to loop through collection each time you want to build the table.
You could then create an instance method to produce the line entry for each instance:
def table_row(self, num): # note argument for fighter number
# return string with appropriate widths
and a class method to do the headers:
#classmethod
def table_header(cls):
# return strings with headers
Then when you print out the table, it looks like:
print Fighter.table_header()
for num, fighter in enumerate(collection, 1):
print fighter.table_row(num)
Here enumerate gives you the number for each Fighter in collection, starting with 1, as well as the actual Fighter objects.

Making a variable cross module in Python - Within a class and function

I'm trying to use a variable in other python modules, like this:
In a.py:
class Names:
def userNames(self):
self.name = 'Richard'
In z.py:
import a
d = a.Names.name
print d
However this doesn't recognise the variable name and the following error is received:
AttributeError: type object 'Names' has no attribute 'name'
Thanks
There are lots of different scopes a variable can be bound to, which is what you seem to be confused about. Here are a few:
# a.py
a = 1 # (1) is module scope
class A:
a = 2 # (2) is class scope
def __init__(self, a=3): # (3) is function scope
self.a = a # (4) self.a is object scope
def same_as_class(self):
return self.a == A.a # compare object- and class-scope variables
def same_as_module(self):
return self.a == a # compare object- and module-scope variables
Now see how these different variables (I only called them all a to make the point, please don't do this for real) are named, and how they all have different values:
>>> import a
>>> a.a
1 # module scope (1)
>>> a.A.a
2 # class scope (2)
>>> obj1 = a.A() # note the argument defaults to 3 (3)
>>> obj1.a # and this value is bound to the object-scope variable (4)
3
>>> obj.same_as_class()
False # compare the object and class values (3 != 2)
>>> obj2 = a.A(2) # now create a new object, giving an explicit value for (3)
>>> obj2.same_as_class()
True
Note we can also change any of these values:
>>> obj1.same_as_module()
False
>>> obj1.a = 1
>>> obj1.same_as_module()
True
For reference, your z.py above should probably look like:
import a
n = a.Names()
d.userNames()
d = n.name
print d
because a.Name is a class, but you're trying to refer to an object-scope variable. An object is an instance of a class: I've called my instance n. Now I have an object, I can get at the object-scope variable. This is equivalent to Goranek's answer.
In terms of my previous example, you were trying to access obj1.a without having an obj1 or anything like it. I'm not really sure how to make this clearer, without turning this into an introductory essay on OO and Python's type system.
"I've checked again and it's because I'm importing from is a Tornado Framework and the variable is within a class."
Accordingly, your problem is not the one shown in your question.
If you actually want to access the variable of a class (and likely, you don't), then do this:
from othermodule import ClassName
print ClassName.var_i_want
You probably want to access the variable as held inside an instance:
from othermodule import ClassName, some_func
classnameinstance = some_func(blah)
print classnameinstance.var_i_want
Update Now that you have completely changed your question, here is the answer to your new question:
IN this code:
class Names:
def userNames(self):
name = 'Richard'
name is not a variable accessible outside of the activation of the method userNames. This is known as a local variable. You would create an instance variable by changing the code to:
def userNames(self):
self.name = 'Richard'
Then, if you have an instance in a variable called classnameinstance you can do:
print classnameinstance.name
This will only work if the variable has been already created on the instance, as by calling userNames.
You don't need to import the class itself if there is some other way to receive instances of the class.
file:a.py
class Names:
def userNames(self):
self.name = 'Richard'
file:z.py
import a
c = a.Names()
c.userNames()
what_you_want_is = c.name
Btw, this code makes no sense..but this is apparently what you want
Better a.py
class Names:
def userNames(self, name):
self.name = name
Better z.py
import a
c = a.Names()
c.userNames("Stephen or something")
what_you_want_is = c.name
# what_you_want_is is "Stephen or something"

Python GAE extend db.Property and add a method [duplicate]

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Google App Engine - how to extend db.IntegerProperty
This is most likely a more general Python query.
I was attempting to inherit and extend one of the db.Property classes in GAE by adding a method that will return an integer representation of a special String value for example:
class DbHHMM(db.StringProperty):
def to_mins(self):
'''Convert the string to minutes'''
arr = re.split(":",self)
ret = 0.0
if (len(arr)==2):
ret = (int(arr[0])*60)+(int(arr[1]))
return ret;
In my model I have a method that sums up a series of these values eg:
class WorkSchedule(db.Model):
'''todo - core hours for the days
TODO is there any way to attach a widgeted form to these via newform = WorkScheduleForm() '''
time1 = DbHHMM()
time2 = DbHHMM()
total = db.IntegerProperty
def sum_times:
self.total = time1.to_mins + time2.to_mins
However when sum_times is called I seem to get the error:
AttributeError: 'unicode' object has no attribute 'to_mins'
Is it possible to add extra methods to the GAE Property classes what are the Python techniques that have been used to prevent this? Am I doing something totally wrong?
Would you mind posting your actual code? your "def sum_times:" is not even valid Python.
My guess is that you want this, and it'll work fine:
class WorkSchedule(db.Model):
time1 = DbHHMM()
time2 = DbHHMM()
total = db.IntegerProperty() # ADDED ()
def sum_times(self): # ADDED (self)
self.total = self.time1.to_mins() + self.time2.to_mins() # ADDED self...() twice

Categories

Resources