I tried to run two thread of class's function, and in function use instance variable. But when I show the adderss of that instance variable, why the address of self.flag of index = 3 is different with remain thread, and why exists two memory of instance variable in one object.
import time, threading, glob
class Test:
def __init__(self):
self.haha = 0
self.flag = True
def start(self, index):
print("start thread index:", index, "self.flag:", self.flag)
threading.Thread(target = self.create, args = (index, )).start()
def stop(self):
self.flag = False
for i in range(1):
time.sleep(1)
if self.flag == True:
print(True)
return True
print(False)
return False
def create(self, index):
print("before go while loop", index,"self.flag", self.flag, "id", id(self.flag)
, "id self:", id(self))
while self.flag:
print("in while loop", index,"self.flag", self.flag, "id", id(self.flag)
, "id self:", id(self))
time.sleep(3)
self.flag = True
a = Test()
a.start(2)
print("Start index: 2")
temp = threading.Thread(target = a.stop)
temp.start()
temp.join()
print("Pre Start index: 3")
a.start(3)
print("After Start index: 3")
print("Pre Start index: 4")
a.start(4)
print("After Start index: 4")
The result like:
start thread index: 2 self.flag: True
before go while loop 2 self.flag True id 7333536 id self: 139774008739392
Start index: 2
in while loop 2 self.flag True id 7333536 id self: 139774008739392
False
Pre Start index: 3
start thread index: 3 self.flag: False
before go while loop 3 self.flag False id 7333504 id self: 139774008739392
After Start index: 3
start thread index: 4 self.flag: True
before go while loop 4 self.flag True id 7333536 id self: 139774008739392
in while loop 4 self.flag True id 7333536 id self: 139774008739392
in while loop 2 self.flag True id 7333536 id self: 139774008739392
Related
I wrote a simple Proxy class in python3, but I have a problem with "was_called" function
class Proxy:
last_invoked = ""
calls = {}
def __init__(self, obj):
self._obj = obj
def __getattr__(self, item):
attrs = dir(self._obj)
if item in attrs:
Proxy.last_invoked = item
if item in Proxy.calls.keys():
Proxy.calls[item] += 1
else:
Proxy.calls[item] = 1
if item in Proxy.calls.keys():
Proxy.calls[item] += 1
else:
Proxy.calls[item] = 1
return getattr(self._obj, item)
else:
raise Exception('No Such Method')
def last_invoked_method(self):
if Proxy.last_invoked == "":
raise Exception('No Method Is Invoked')
else:
return Proxy.last_invoked
def count_of_calls(self, method_name):
if method_name in Proxy.calls.keys():
return Proxy.calls[method_name]
return 0
def was_called(self, method_name):
if method_name in Proxy.calls.keys():
if Proxy.calls[method_name] > 0: return True
return False
class Radio():
def __init__(self):
self._channel = None
self.is_on = False
self.volume = 0
def get_channel(self):
return self._channel
def set_channel(self, value):
self._channel = value
def power(self):
self.is_on = not self.is_on
radio = Radio()
radio_proxy = Proxy(radio)
radio.number = 3
radio_proxy.number = 3
radio_proxy.power()
print(radio_proxy.was_called("number"))
print(radio_proxy.was_called("power"))
"was_called" function is work for functions and attributes that is in radio at first such as "power", but it's not work for new attributes that we add such as "number".
I expect for both print "True", because both of "power" and "number" is called. but first print return False!
What do you suggest?
def Proxy(class_type):
class ProxyClass(class_type):
def __init__(self, *args, **kwargs):
# Set your _calls and _last_invoked here, so that they are not class attributes (and are instead instance attributes).
self._calls = {}
self._last_invoked = ""
# Pass the arguments back to the class_type (in our case Radio) to initialize the class.
super().__init__(*args, **kwargs)
def __getattribute__(self, item):
# We must do this prelimary check before continuing on to the elif statement.
# This is since _calls and _last_invoked is grabbed when self._last_invoked/self._calls is called below.
if item in ("_calls", "_last_invoked"):
return super(ProxyClass, self).__getattribute__(item)
elif not item.startswith("_"):
self._last_invoked = item
self._calls[item] = 1 if item not in self._calls.keys() else self._calls[item] + 1
return super(ProxyClass, self).__getattribute__(item)
def __setattr__(self, item, val):
# Wait until _calls is initialized before trying to set anything.
# Only set items that do not start with _
if not item == "_calls" and not item.startswith("_"):
self._calls[item] = 0
super(ProxyClass, self).__setattr__(item, val)
def last_invoked_method(self):
if self._last_invoked == "":
raise Exception('No Method Is Invoked')
else:
return self._last_invoked
def count_of_calls(self, method_name):
return self._calls[method_name] if method_name in self._calls.keys() else 0
def was_called(self, method_name):
return True if method_name in self._calls.keys() and self._calls[method_name] > 0 else False
return ProxyClass
#Proxy
class Radio():
def __init__(self):
self._channel = None
self.is_on = False
self.volume = 0
def get_channel(self):
return self._channel
def set_channel(self, value):
self._channel = value
def power(self):
self.is_on = not self.is_on
radio = Proxy(Radio)()
radio.number = 3 # Notice that we are only setting the digit here.
radio.power()
print(radio._calls)
print(radio.number) # Notice that this when we are actually calling it.
print(radio._calls)
outputs:
{'is_on': 0, 'volume': 0, 'number': 0, 'power': 1}
3
{'is_on': 0, 'volume': 0, 'number': 1, 'power': 1}
A few modifications here and there, but you should be able to see the bigger idea by reading through the code. From here you should be able to modify the code to your liking. Also note that any variable that starts with _ is automatically removed from the _calls dictionary.
If you rather not use the decorator #Proxy, you may initialize your Radio class (as a proxy) like so:
# Second parentheses is where your Radio args go in.
# Since Radio does not take any args, we leave it empty.
radio_proxy = Proxy(Radio)()
Also, make sure to understand the difference between class attributes, and instance attributes.
Edit:
class Test:
def __init__(self, var):
self.var = var
self.dictionary = {}
def __getattribute__(self, item):
print("we are GETTING the following item:", item)
# If we don't do this, you end up in an infinite loop in which Python is
# trying to get the `dictionary` class to do `self.dictionary['dictionary'] = ...`
if item == "dictionary":
super(Test, self).__getattribute__(item)
else:
self.dictionary[item] = "Now we can use this!"
return super(Test, self).__getattribute__(item)
def __setattr__(self, item, key):
print("we are SETTING the following item:", item)
super(Test, self).__setattr__(item, key)
Notice:
test = Test(4)
outputs:
we are SETTING the following item: var
we are SETTING the following item: dictionary
then following it:
test.var
outputs:
we are GETTING the following item: var
we are GETTING the following item: dictionary
I have three classes which I want to call and save them dependant on list contents. I want to figure out how to call two classes and call values within tow classes and save them, when I want to call them later, that classes remember and display what a user has been selected.
The code:
_list = [0, 1, 2, 3, 4]
class Data(object):
def __init__(self):
self.ID = 'Data_id'
self.first = 'Data_1'
self.second = 'Data_2'
self.third = 'Data_3'
class Value(object):
def __init__(self):
self.ID = 'Value_id'
self.first = 'Value_1'
self.second = 'Value_2'
self.third = 'Value_3'
class Base(object):
def __init__(self):
self.item = -1
if self.item == 1 or self.item == 2:
self.first_class = Data()
self.second_class = Value()
print('Item:', self.item, 'Class_ID: {}'.format( self.first_class.second))
print('Item:', self.item, 'Class_ID: {}'.format( self.second_class.first))
elif self.item == 2 or self.item == 4:
self.first_class = Data()
self.second_class = Value()
print('Item:', self.item, 'Class_ID: {}'.format( self.first_class.first))
print('Item:', self.item, 'Class_ID: {}'.format( self.second_class.third))
else:
self.first_class = Data()
self.second_class = Value()
print('Item:', self.item, 'Class_ID: {}'.format( self.first_class.ID))
print('Item:', self.item, 'Class_ID: {}'.format( self.second_class.ID))
run = Base()
for i in _list:
run.item = _list[i]
_list values changes every time, it could be None or any int number from 0 to 9 for example. The idea is to call two classes Data and Value every time an item from list is initialized. Then the values within the classes are called for example item 1 is called then the tow classes run and values are called.
print('Item:', self.item, 'Class_ID: {}'.format( self.first_class.first))
print('Item:', self.item, 'Class_ID: {}'.format( self.second_class.third))
After execution of for-loop, user want to run following code or to know which values from which class is called at item = 3
run.item = _list[3]
How can I achieve this behaviour?
I appreciate any help. In advance thanks.
___init___ is a special method which supposed to run exactly once when the class is initialized. When you call run = Base() the logic runs, self.item will be evaluated as -1
What your class does is basically this:
controls = [0,1]
class Controlled:
def __init__(self):
self.param = -1
if self.param == 0:
print(0)
elif self.param == 1:
print(1)
else:
print('This is not unexpected')
c = Controlled()
for p in controls:
c.param = p
If you run Controlled(), the self.param will be -1 every time during the initialization, the else branch will print the This is not unexpected message. The
for p in controls:
c.param = p
part basically just updates the class attribute but does not call anything, nothing will be printed or executed.
I think you wanted to implement something like this:
controls = [0,1]
class Controlled:
def __init__(self, param=-1):
self.param = param
if self.param == 0:
print(0)
elif self.param == 1:
print(1)
else:
print('This is not unexpected')
results = []
for p in controls:
results.append(Controlled(p))
When you call __init__(self, param=-1), the given parameter (p) will be taken into account and the init logic will run based on the given parameter.
Code first so you'll understand what I'm talking about :
goal = False
count = 0
def function():
if goal==True:
return True
else:
return False
def func():
if dict1["A"]==True:
return True
else:
return False
dict1 = {"A":function()}
dict2 = {"B":func()}
list = [dict1,dict2]
goal = True
for i in list:
count = 0
for x,y in i.items():
if y==True:
count+=1
if count==len(i):
print("Works")
else:
print(i)
>>>{"A":False}
>>>{"B":False}
This is not my current code, but it is the actual issue. This is where I'm asking, how can I update the values in the dicts. Should I do something like :
for i in list:
for x,y in i.items():
y()
?
My current project is used in Ren'Py (.rpy) but as I'm using python blocks, the code works exactly as normal Python.
Within a class named Event, my elements are exactly as it follows:
def ev_check(self):
if self.done==False:
self.count = 0
for x,y in self.conditions.items():
if y==True:
self.count+=1
else:
pass
if self.count==len(self.conditions):
self.valid = True
else:
self.valid = False
else:
self.valid = False
def own_office():
if Promotion_1.done==True: #Once the event is played, .done gets True
return True
else:
return False
def times_worked(x):
if You.worked < x:
return False
else:
return True
Promotion_1.conditions = {"Work 2 times" : times_worked(2)}
Meet_Tigerr.conditions = {"Own office" : own_office()}
#External event that adds a value to the data named You.worked to get it to 2
print(Promotion_1.conditions["Work 2 times"])
>>> False
Expected result : True
Result : False
You can create your custom dict and have this feature. You may try something like this:
class MyDict(dict):
def __getitem__(self, item):
val = super().__getitem__(item)
if callable(val):
return val()
return val
It will work exactly like a dict, except that it will call the callable values for you every time.
d = MyDict()
d['m'] = 1
d['m']
Out[28]: 1
task
Out[33]: <function __main__.task()>
task()
Out[34]: True
d['t'] = task
d['t']
Out[36]: True
EDITED : Modified the code a bit to show how you can even have argument values passed for your parameterized functions:
def func():
return True
def param_func(i):
return 2*i
def param_func2(i, j):
return i*j
class MyDict(dict):
def __getitem__(self, key):
if isinstance(key, tuple):
super_key = key[0]
else:
super_key = key
super_val = super().__getitem__(super_key)
if callable(super_val):
if isinstance(key, tuple):
args = key[1:]
return super_val.__call__(*args)
else:
return super_val.__call__()
return super_val
if __name__ == "__main__":
d = MyDict()
d['num'] = 1
print(d['num'])
d['func'] = func
print(d['func'])
d['param_func'] = param_func
print(d['param_func', 2])
d['param_func2'] = param_func2
print(d['param_func2', 2, 6])
Output :
1
True
4
12
Because stack allows to either push or pop, it is suitable to redo actions by just simply popping the latest action by the user. I have a stack class where:
class Node:
def __init__(self,item,the_next = None):
self.item = item
self.next = the_next
def __str__(self):
return str(self.item)
class LinkedStack:
def __init__(self):
self.top = None
self.count = 0
def __len__(self):
return self.count
def is_empty(self):
return self.count == 0
def isFull(self):
return False
def reset(self):
self.top = None
self.count = 0
def __str__(self):
current = self.top
ans = ""
while not (current is None):
ans += str(current)
ans += '\n'
current = current.next
return ans
def _get_node(self,index):
if 0<= index< len(self):
current = self.top
while index>0:
current = current.next
index -=1
return current
def pop(self):
if self.is_empty():
raise StopIteration("Stack is empty")
output = self.top.item
self.top = self.top.next
self.count -=1
return output
def push(self,item):
newNode = Node(item)
newNode.next = self.top
self.top = newNode
self.count +=1
if __name__ == "__main__":
L = LinkedStack()
and in another file, i import the stack from above and try to implement the undo action.
from Stack import LinkedStack
class Editor:
def __init__(self):
self.count = 0
self._list = LinkedList()
self._stack = LinkedStack()
def command(self,userCommand):
userCommand = userCommand.split(' ')
try:
if userCommand[0] == 'insert':
position = int(userCommand[1])
if len(userCommand) ==1:
raise Exception('no num is given')
textInput = input("Enter your text:")
self._stack.push(self.insertText(position,textInput)) #I'm thinking of adding the action into the stack by pushing it.
print(self._list)
pass
except Exception:
print('?')
if userCommand[0] == 'undo': #here if they choose to undo, by right i just pop the last action from the stack
self._stack.pop()
if __name__ == '__main__':
myCommand = Editor()
while True:
command = input('Enter an option:')
if command.lower() == 'quit':
break
else:
myCommand.command(command)
because I'm merely undoing actions, i thought of adding the command actions into a stack. if you take a look at the insert command above, where i added a comment, am i doing it correctly? Because I'm running out of ideas.
By the way, the insertText is a function which is working and I'm not planning to paste it here as it's getting lengthy. LinkedList() is just a linked list class i imported from another file as well.
The 'undo' doesn't seemed to revert the state. For example, if my LinkedList() contains:
1
2
3
4
None
and if i use the insert function to insert another number, 7 at index 1
1
7
2
3
4
None
and if i undo the action, I'm supposed to have:
1
2
3
4
None
I am going through a data structures course and I am not understanding how a Class can call a method that's in another Class.
The code below has 2 classes: Printer and Task.
Notice that class Printer has a method called startNext, and this has a variable self.timeRemaining that gets assigned the result of newTask.getPages() * 60/self.pagerate.
How can newTaks reference the getPages() method from the Task class?
The code that passes this object to the Printer class never references the Task class.
The code works, since this is what the course gives out but, I just cannot understand how that method is accessed.
Code:
from pythonds.basic.queue import Queue
import random
class Printer:
def __init__(self, ppm):
self.pagerate = ppm
self.currentTask = None
self.timeRemaining = 0
def tick(self):
if self.currentTask != None:
self.timeRemaining = self.timeRemaining - 1
if self.timeRemaining <= 0:
self.currentTask = None
def busy(self):
if self.currentTask != None:
return True
else:
return False
def startNext(self, newTask):
self.currentTask = newTask
self.timeRemaining = newTask.getPages() * 60/self.pagerate
class Task:
def __init__(self, time):
self.timeStamp = time
self.pages = random.randrange(1, 21)
def getStamp(self):
return self.timeStamp
def getPages(self):
return self.pages
def waitTime(self, currentTime):
return currentTime - self.timeStamp
def simulation(numSeconds, pagesPerMinute):
labPrinter = Printer(pagesPerMinute)
printQueue = Queue()
waitingTimes = []
for currentSecond in range(numSeconds):
if newPrintTask():
task = Task(currentSecond)
printQueue.enqueue(task)
if (not labPrinter.busy()) and (not printQueue.isEmpty()):
nextTask = printQueue.dequeue()
waitingTimes.append(nextTask.waitTime(currentSecond))
labPrinter.startNext(nextTask)
labPrinter.tick()
averageWait = sum(waitingTimes)/len(waitingTimes)
print "Average Wait %6.2f secs %3d tasks remaining." % (averageWait, printQueue.size())
def newPrintTask():
num = random.randrange(1, 181)
if num == 180:
return True
else:
return False
for i in range(10):
simulation(3600, 5)
If I understand clearly your question, it is because you are adding task object to Queue list. Then when you are getting object (list item) back, you are getting again Task object:
#creating Task object and adding to Queque list
task = Task(currentSecond)
printQueue.enqueue(task)
class Queue:
def __init__(self):
#list of task objects
self.items = []
def enqueue(self, item):
#you are inserting Task object item to list
self.items.insert(0,item)
def dequeue(self):
#returns task object
return self.items.pop()
So then you can call startNext() method from Printer class, because the dequeue() method is returning Task object.
And because of the object in startNext() is type of Task, you can call getPages() method on that object.
Is it sufficient answer?