I having difficulties to understand the instance of an object in a list.
How to save the value of an object into a list without saving the instance?
This is not possible isnt it?
The colde below works but i would like to avoid to use .value as i might have several parameters.. not sure if i am clear enough..
class BougieBuffer:
def __init__(self):
self.bougiebuffer=deque(maxlen = 10000)
self.maximum = Maximum()
def update(self,bougie):
self.maximum.value = random.randint(-1,1)
bougie.maximum.value = self.maximum.value
self.bougiebuffer.append(bougie)
print len(self.bougiebuffer)
for i in range (len(self.bougiebuffer),0,-1):
print self.bougiebuffer[i-1].prixFermeture, self.bougiebuffer[i-1].maximum.value
I would have wrote naturally something like below but obviously this is not working and it returns the same value for all
bougie.maximum = self.maximum
You want to create a copy of the Maximum() instance to assign to the bougie.maximum attribute; use either copy.copy or copy.deepcopy:
from copy import deepcopy
bougie.maximum = deepcopy(self.maximum)
You'll need deepcopy if there are any attributes of Maximum that are mutable; a list, dict, set or another custom class instance are all mutable, but things like integers and strings are not.
Related
I came across a method in Python that returns a class, but can be destructured as if it's a tuple.
How can you define a result of a function to be both an instance of a class AND use destructure assignment as if it's a tuple?
An example where you see this behavior:
import scipy.stats as stats
res = stats.ttest_ind(data1, data2)
print(type(res)) # <class 'scipy.stats.stats.Ttest_indResult'>
# One way to assign values is by directly accessing the instance's properties.
p = res.pvalue
t = res.statistic
# A second way is to treat the result as a tuple, and assign to variables directly. But how is this working?
# We saw above that the type of the result is NOT a tuple but a class. How would Python know the order of the properties here? (It's not like we're destructuring based on named properties)
t, p = stats.ttest_ind(data1, data2)
It's a named tuple, which is basically an extension to tuple type in python.
To unpack a data type with a, b = some_object, the object on the right side needs to be iterable. A list or tuple works, obviously, but you can make your own class iterable by implementing an __iter__ method.
For example, the following class would behave consistently with the interface you've shown the Ttest_indResult class to have (though it's probably implemented very differently):
class MyClass:
def __init__(self, statistic, pvalue):
self.statistic = statistic # these attributes are accessible by name
self.pvalue = pvalue
def __iter__(self): # but you can also iterate to get the same values
yield self.statistic
yield self.pvalue
I created a class, something like below -
class child:
def __init__(self,lists):
self.myList = lists
def find_mean(self):
mean=np.mean(self.myList)
return mean
and when I create an onject something like below -
obj=child()
it gives the error -
TypeError: __init__() missing 1 required positional argument: 'lists'
if I create object like below then it works well -
obj=child([44,22,55)
or If I create the class like below -
class child:
def find_mean(self,myList):
mean=np.mean(myList)
return mean
and then I create the object like below -
obj=child()
then also it works well, however I need to make it in the way I explained in the very begining. Can you please help me understand this context?
In the first example, the __init__ method expects two parameters:
self is automatically filled in by Python.
lists is a parameter which you must give it. It will try to assign this value to a new variable called self.myList, and it won't know what value it is supposed to use if you don't give it one.
In the second example, you have not written an __init__ method. This means that Python creates its own default __init__ function which will not require any parameters. However, the find_mean method now requires you to give it a parameter instead.
When you say you want to create it in the way you explained at the beginning, this is actually impossible: the class requires a value, and you are not giving it one.
Therefore, it is hard for me to tell what you really want to do. However, one option might be that you want to create the class earlier, and then add a list to it later on. In this case, the code would look like this:
import numpy as np
class Child:
def __init__(self, lists=None):
self.myList = lists
def find_mean(self):
if self.myList is None:
return np.nan
mean = np.mean(self.myList)
return mean
This code allows you to create the object earlier, and add a list to it later. If you try to call find_mean without giving it a list, it will simply return nan:
child = Child()
print(child.find_mean()) # Returns `nan`
child.myList = [1, 2, 3]
print(child.find_mean()) # Returns `2`
the code you have at the top of your question defines a class called child, which has one attribute, lists, which is assigned at the time of instance creation in the __init__ method. This means that you must supply a list when creating an instance of child.
class child:
def __init__(self, lists):
self.myList = lists
def find_mean(self):
mean=np.mean(self.myList)
return mean
# works because a list is provided
obj = child([44,22,55])
# does not work because no list is given
obj = child() # TypeError
If you create the class like in your second example, __init__ is no longer being explicitly specified, and as such, the object has no attributes that must be assigned at instance creation:
class child:
def find_mean(self, myList):
mean=np.mean(myList)
return mean
# does not work because `child()` does not take any arguments
obj = child([44,22,55]) # TypeError
# works because no list is needed
obj = child()
The only way to both have the myList attribute, and not need to specify it at creation would be to assign a default value to it:
class child:
def find_mean(self,myList=None):
mean=np.mean(myList)
return mean
# now this will work
obj = child()
# as will this
obj = child([24, 35, 27])
What does "CmdBtn['menu'] = CmdBtn.menu" in second last line mean.
def makeCommandMenu():
CmdBtn = Menubutton(mBar, text='Button Commands', underline=0)
CmdBtn.pack(side=LEFT, padx="2m")
CmdBtn.menu = Menu(CmdBtn)
...
...
CmdBtn['menu'] = CmdBtn.menu
return CmdBtn
When you use x[y] = z, it calls the __setitem__ method.
i.e.
x.__setitem__(y, z)
In your case, CmdBtn['menu'] = CmdBtn.menu means
CmdBtn.__setitem__('menu', CmdBtn.menu)
The Menubutton class does indeed provide a __setitem__ method. It looks like this is used to set a "resource value" (in this case CmdBtn.menu) for the given key ('menu').
This is not a "string inside an array".
The brackets operator is used for item access in some kind of sequence (usually a list, or a tuple), mapping (usually a dict, or dictionary), or some other kind of special object (such as this MenuButton object, which is not a sequence or a mapping). Unlike in some other languages, in python, ANY object is allowed to make use of this operator.
A list is similar to an "array" in other languages. It can contain a mixture of objects of any kind, and it maintains the order of the objects. A list object is very useful for when you want to maintain an ordered sequence of objects. You can access an object in a list using its index, like this (indexes start at zero):
x = [1,2,3] # this is a list
assert x[0] == 1 # access the first item in the list
x = list(range(1,4)) # another way to make the same list
A dict (dictionary) is useful for when you want to associate values with keys so you can look up the values later using the keys. Like this:
d = dict(a=1, b=2, c=3) # this is a dict
assert x['a'] == 1 # access the dict
d = {'a':1, 'b':2, 'c':3} # another way to make the same dict
Finally, you may also encounter custom made objects that also use the same item-access interface. In the Menubutton case, ['menu'] simply accesses some item (defined by the tkinter API) that responds to the key, 'menu'. You can make your own object type with item-access, too (python 3 code below):
class MyObject:
def __getitem__(self, x):
return "Here I am!"
This object doesn't do much except return the same string for key or index value you give it:
obj = MyObject()
print(obj [100]) # Here I am!
print(obj [101]) # Here I am!
print(obj ['Anything']) # Here I am!
print(obj ['foo bar baz']) # Here I am!
First of all, in Python everything is an object and square brackets means that this object is subscriptable (for e.g. tuple, list, dict, string and many more). Subscriptable means that this object at least implements the __getitem__() method (and __setitem__() in your case).
With those methods it's easy to interact with class members, so don't afraid to build your own example, to understand someone else's code.
Try this snippet:
class FooBar:
def __init__(self):
# just two simple members
self.foo = 'foo'
self.bar = 'bar'
def __getitem__(self, item):
# example getitem function
return self.__dict__[item]
def __setitem__(self, key, value):
# example setitem function
self.__dict__[key] = value
# create an instance of FooBar
fb = FooBar()
# lets print members of instance
# also try to comment out get and set functions to see the difference
print(fb['foo'], fb['bar'])
# lets try to change member via __setitem__
fb['foo'] = 'baz'
# lets print members of instance again to see the difference
print(fb['foo'], fb['bar'])
It is shorthand for CmdBtn.configure(menu=CmdBtn.menu)
The way to set widget options is typically at creation time (eg: Menubutton(..., menu=...)) or using the configure method (eg: CmdBtn.configure(menu=...). Tkinter provides a third method, which is to treat the widget like a dictionary where the configuration values are keys to the dictionary (eg: CMdBtn['menu']=...)
This is covered in the Setting Options section of the official python tkinter documentation
How to return a list of objects and not list here.
I want to return a list of test objects and not a list of str..
class test:
val = ""
def __init__(self,v):
self.val = v
def tolower(self,k):
k = k.val.lower()
return k
def test_run():
tests_lst = []
tests_lst.append(test("TEST-0"))
tests_lst.append(test("TEST-1"))
tests_lst.append(test("TEST-2"))
i_want_object_of_test = map(lambda x:x.val.lower(),tests_lst)
if __name__ == '__main__':
test_run()
OUTPUT:
['test-0', 'test-1', 'test-2']
i want a list of test objects where each object's val has changed to lower case.
The question is unclear. I'll answer by what I understand.
What I understand is that you are trying to create a new list of test objects, with the values as lower case.
You can do this either by changing the state of each of the objects in a for loop (changing state is usually not recommended):
for test_obj in test_lst:
test_obj.val = test_obj.val.lower()
A way to do it through a list comprehension is to create new test instances:
i_want_object_of_test = [test(test_obj.val.lower()) for test_obj in test_lst]
Besides, there are a few problems with your test class:
It is an old style class, you should always inherit from object in your classes: class test(object):
You define a class variable by putting val = ""' in your class defenition, you then override it in each instance.
Your tolower method gets another test instance (k) and returns its value as lower case. I assume you want to either return a new test object or change the current one in place. Either way the method should only use self.
I am reading a binary file into a list of class instances. I have a loop that reads data from the file into an instance. When the instance is filled, I append the instance to a list and start reading again.
This works fine except that one of the elements of the instance is a Rect (i.e. rectangle), which is a user-defined type. Even with deepcopy, the attributes are overwritten.
There are work-arounds, like not having Rect be a user-defined type. However, I can see that this is a situation that I will encounter a lot and was hoping there was a straightforward solution that allows me to read nested types in a loop.
Here is some code:
class Rect:
def __init__(self):
self.L = 0
class groundtruthfile:
def __init__(self):
self.rect = Rect
self.ht = int
self.wt = int
self.text = ''
...
data = []
g = groundtruthfile()
f = open("datafile.dtf", "rb")
length = unpack('i', f.read(4))
for i in range(1,length[0]+1): #length is a tuple
g.rect.L = unpack('i',f.read(4))[0]
...
data.append(copy.deepcopy(g))
The results of this are exactly what I want, except that all of the data(i).rect.L are the value of the last data read.
You have two problems here:
The rect attribute of a groundtruthfile instance (I'll just put this here...) is the Rect class itself, not an instance of that class - you should be doing:
self.rect = Rect() # note parentheses
to create an instance, instead (similarly e.g. self.ht = int sets that attribute to the integer class, not an instance); and
The line:
g.rect.L = unpack('i',f.read(4))[0]
explicitly modifies the attribute of the same groundtruthfile instance you've been using all along. You should move the line:
g = groundtruthfile()
inside the loop, so that you create a separate instance each time, rather than trying to create copies.
This is just a minimal fix - it would make sense to actually provide arguments to the various __init__ methods, for example, such that you can create instances in a more intuitive way.
Also, if you're not actually using i in the loop:
for _ in range(length[0]):
is neater than:
for i in range(1,length[0]+1):