I can't get parallel reference working when using map and dict like argument.
from IPython import parallel
from IPython.parallel import Client
from IPython.parallel import Reference
rc = Client()
dview = rc.direct_view()
dview.block = True
dview['l'] = [0, 1]
kws = [{'l': Reference('l')}]
def second(kws):
l = kws['l']
return l[1]
dview.apply(second, kws[0])
Returns:
[1, 1, 1, 1, 1, 1, 1, 1]
But:
dview.map(second, kws)
Returns:
TypeError: 'Reference' object does not support indexing
The problem is that the unserialization does not handle nested structures well. You can see this for yourself like this:
from IPython.core.display import display
from IPython.kernel.zmq.serialize import serialize_object, unserialize_object
from IPython.parallel import Reference
l = 5
ref = Reference('l')
kws = [dict(l=ref)]
display(unserialize_object(serialize_object(kws), g=globals()))
# outputs ([{'l': <Reference: 'l'>}], [])
display(unserialize_object(serialize_object(kws[0]), g=globals()))
# outputs ({'l': 5}, [])
I'm not an IPython developer but looking around the code I found a very simple way to fix it. In ipykernel/pickleutil.py (or IPython/utils/pickleutil.py), there is a dictionary that maps types to unserialization methods:
uncan_map = {
CannedObject : lambda obj, g: obj.get_object(g),
}
Simply adding dict fixes the problem:
uncan_map = {
CannedObject : lambda obj, g: obj.get_object(g),
dict : uncan_dict,
}
I will make a pull request for the ipykernel project referencing this question.
Related
I'm using ROS, and writing some codes to do some tasks, and now I'm facing an error: TypeError: must be real number, not RestMode, for more details, I have code here:
#!/usr/bin/env python
#encoding: utf-8
import rospy
from geometry_msgs.msg import Vector3
from sensor_msgs.msg import Imu
from std_msgs.msg import Float64
import numpy as np
import geometry as geo
import transformation as tf
from IK_solver import IK
class RestMode:
def __init__(self, bodyDimensions, legDimensions):
# rospy.Subscriber('spot_keyboard/body_pose',Vector3,self.callback)
self.bodyLength = bodyDimensions[0]
self.bodyWidth = bodyDimensions[1]
self.bodyHeight = bodyDimensions[2]
self.l1 = legDimensions[0]
self.l2 = legDimensions[1]
self.l3 = legDimensions[2]
# rospy.Subscriber('spot_imu/base_link_orientation',Imu, self.get_body_pose)
self.rate = rospy.Rate(10.0) #10Hz
self.rb = IK(bodyDimensions, legDimensions)
angles_cmd = [ 'spot_controller/FL1_joint/command',
'spot_controller/FL2_joint/command',
'spot_controller/FL3_joint/command',
'spot_controller/RL1_joint/command',
'spot_controller/RL2_joint/command',
'spot_controller/RL3_joint/command',
'spot_controller/RR1_joint/command',
'spot_controller/RR2_joint/command',
'spot_controller/RR3_joint/command',
'spot_controller/FL1_joint/command',
'spot_controller/FL2_joint/command',
'spot_controller/FL3_joint/command' ]
self.joint = []
for i in range(12):
self.joint.append(rospy.Publisher(angles_cmd[i], Float64, queue_size=10))
# self.initial_pose()
def initial_pose(self,roll=0,pitch=0,yaw=0,dx=0,dy=0,dz=None):
if dz == None:
dz = self.bodyHeight
order = ['FL','RL','RR','FR']
angles = []
rospy.loginfo("Start Calculate Angles!")
for leg in order:
(q1,q2,q3,ht) = self.rb.calculateAngles(self,roll,pitch,yaw,dx,dy,dz,leg)
angles.append(q1)
angles.append(q2)
angles.append(q3)
rospy.loginfo("Done! Start publish!")
for i in range(12):
self.joint[i].publish(angles[i])
self.rate.sleep()
if __name__ == '__main__':
rospy.init_node('rest_mode', anonymous=True)
body = [0.1908, 0.080, 0.15]
legs = [0.04, 0.1, 0.094333]
rest = RestMode(body, legs)
try:
while not rospy.is_shutdown():
rest.initial_pose()
except rospy.ROSInterruptException:
pass
When method calculateAngles(self,roll,pitch,yaw,dx,dy,dz,leg) with argument leg in last, it throws: TypeError: must be real number, not RestMode.
But when I change it to first like: calculateAngles(self,leg,roll,pitch,yaw,dx,dy,dz), then error says: TypeError: must be real number, not str with input in another module, but I tested all of the others related module, and they are fine, so I think that must be an issue in codes above!
That error is so strange:
I don't push any str as input
When changing the position of argument leg, it throws a different error.
When calling instance methods, self is an implied parameter, and should never be explicitly passed. When you are using self.rb.calculateAngles(self, ..., that second self is an instance of a RestMode class, which your IK class does not accept...
Therefore, you want
(q1,q2,q3,ht) = self.rb.calculateAngles(roll,pitch,yaw,dx,dy,dz,leg)
And change other usages within the IK class as well
For python3, I originally needed to extract odd and even positions from a list and assign it to new lists, then clear the original list. I thought lists were impacted by a function call through "pass by reference". Testing some scenarios, it works sometime. Could someone please explain how exactly python3 works here?
Case 1: empty list is populated with string as expected.
def func1(_in):
_in.append('abc')
mylist = list()
print(f"Before:\nmylist = {mylist}")
func1(mylist)
print(f"After:\nmylist = {mylist}")
Output case 1:
Before:
mylist = []
After:
mylist = ['abc']
Case 2: middle list element is replaced with string as expected.
def func2(_in):
_in[1] = 'abc'
mylist = list(range(3))
print(f"Before:\nmylist = {mylist}")
func2(mylist)
print(f"After:\nmylist = {mylist}")
Output case 2:
Before:
mylist = [0, 1, 2]
After:
mylist = [0, 'abc', 2]
Case 3: why is the list not empty after function call?
def func3(_in):
_in = list()
mylist = list(range(3))
print(f"Before:\nmylist = {mylist}")
func3(mylist)
print(f"After:\nmylist = {mylist}")
Output case 3:
Before:
mylist = [0, 1, 2]
After:
mylist = [0, 1, 2]
Case 4: working exactly as expected, but note I have returned all three lists from function.
def func4_with_ret(_src, _dest1, _dest2):
_dest1 = [val for val in _src[0:len(_src):2]]
_dest2 = [val for val in _src[1:len(_src):2]]
_src = list()
return _src, _dest1, _dest2
source = list(range(6))
evens, odds = list(), list()
print(f"Before function call:\nsource = {source}\nevens = {evens}\nodds = {odds}")
source, evens, odds = func4_with_ret(source, evens, odds)
print(f"\nAfter function call:\nsource = {source}\nevens = {evens}\nodds = {odds}")
Output case 4:
Before function call:
source = [0, 1, 2, 3, 4, 5]
evens = []
odds = []
After function call:
source = []
evens = [0, 2, 4]
odds = [1, 3, 5]
Case 5: why no impact on the variables outside the function if I do not explicitly return from function call?
def func5_no_ret(_src, _dest1, _dest2):
_dest1 = [val for val in _src[0:len(_src):2]]
_dest2 = [val for val in _src[1:len(_src):2]]
_src = list()
source = list(range(6))
evens, odds = list(), list()
print(f"Before function call:\nsource = {source}\nevens = {evens}\nodds = {odds}")
func5_no_ret(source, evens, odds)
print(f"\nAfter function call:\nsource = {source}\nevens = {evens}\nodds = {odds}")
Output case 5:
Before function call:
source = [0, 1, 2, 3, 4, 5]
evens = []
odds = []
After function call:
source = [0, 1, 2, 3, 4, 5]
evens = []
odds = []
Thank you.
Your ultimate problem is confusing (in-place) mutation with rebinding (also referred to somewhat less precisely as "reassignment").
In all the cases where the change isn't visible outside the function, you rebound the name inside the function. When you do:
name = val
it does not matter what used to be in name; it's rebound to val, and the reference to the old object is thrown away. When it's the last reference, this leads to the object being cleaned up; in your case, the argument used to alias an object also bound to a name in the caller, but after rebinding, that aliasing association is lost.
Aside for C/C++ folks: Rebinding is like assigning to a pointer variable, e.g. int *px = pfoo; (initial binding), followed later by px = pbar; (rebinding), where both pfoo and pbar are themselves pointers to int. When the px = pbar; assignment occurs, it doesn't matter that px used to point to the same thing as pfoo, it points to something new now, and following it up with *px = 1; (mutation, not rebinding) only affects whatever pbar points to, leaving the target of pfoo unchanged.
By contrast, mutation doesn't break aliasing associations, so:
name[1] = val
does rebind name[1] itself, but it doesn't rebind name; it continues to refer to the same object as before, it just mutates that object in place, leaving all aliasing intact (so all names aliasing the same object see the result of the change).
For your specific case, you could change the "broken" functions from rebinding to aliasing by changing to slice assignment/deletion or other forms of in-place mutation, e.g.:
def func3(_in):
# _in = list() BAD, rebinds
_in.clear() # Good, method mutates in place
del _in[:] # Good, equivalent to clear
_in[:] = list() # Acceptable; needlessly creates empty list, but closest to original
# code, and has same effect
def func5_no_ret(_src, _dest1, _dest2):
# BAD, all rebinding to new lists, not changing contents of original lists
#_dest1 = [val for val in _src[0:len(_src):2]]
#_dest2 = [val for val in _src[1:len(_src):2]]
#_src = list()
# Acceptable (you should just use multiple return values, not modify caller arguments)
# this isn't C where multiple returns are a PITA
_dest1[:] = _src[::2] # Removed slice components where defaults equivalent
_dest2[:] = _src[1::2] # and dropped pointless listcomp; if _src might not be a list
# list(_src[::2]) is still better than no-op listcomp
_src.clear()
# Best (though clearing _src is still weird)
retval = _src[::2], _src[1::2]
_src.clear()
return retval
# Perhaps overly clever to avoid named temporary:
try:
return _src[::2], _src[1::2]
finally:
_src.clear()
Problem
I have a string and scores for each char in the string
text = 'text'
scores = [0.99, 0.98, 0.97, 0.96]
I would like to do many string operations to text, like re, +, slice or split, after do these operations, I want to keep correspond scores. For example, if I do a slice operation I want get sliced_text and sliced_scores as result:
sliced_text = text[0:2]
sliced_scores = scores[0:2]
Python3 has UserString class, for some simple operations like slice or add, it's very useful.
from collections import UserString
from typing import List
class ScoreString(UserString):
def __init__(self, text: str, scores: List[float]):
super().__init__(text)
assert len(text) == len(scores)
self.scores = scores
def __getitem__(self, index) -> 'ScoreString':
return self.__class__(self.data[index], self.scores[index])
def __add__(self, other) -> 'ScoreString':
return self.__class__(self.data + other.data, self.scores + other.scores)
score_str = ScoreString('Test123', [1, 2, 3, 4, 5, 6, 7])
a = score_str[0:2] + score_str[4:]
print(a.data) # Te123
print(a.scores) # [1, 2, 5, 6, 7]
But split or re not work.
print(score_str.split('12')) # return string list ['Test', '3'], lose scores
import re
re.sub('123', '', score_str) # TypeError: expected string or bytes-like object
Any suggestion?
Actually what you are trying to do in split function
score_str.split('12')
--> Here score_str is a class object which is inheriting UserString, so when you apply split function it will call the function of base class and you will get a normal output as str.split().
import re
re.sub('123', '', score_str)
--> Here when you are trying to implement regular expression, Then sub functions have arguments sub(pattern, repl, string, count=0, flags=0), but here in third argument you are passing score_str, which is an object of ScoreString. That is why you are getting error.
If you will re-write as below,
re.sub('123', '', score_str.data)
It should work..
I hope this will help.
I am trying to create some more functional code in Python and I want to know if it is possible to transform dictionary (key,values) to pass as a function parameter.
I am currently doing this in a more imperative way, where I filter and then manually extract each key depending on the result of the filter. My current code:
def a(i: int, config: dict):
function_array = [function1, function2, function3]
selected = function_array[i]
if (i == "0"):
result = selected(x = config['x'])
elif (i == "1"):
result = selected(y = config['y'])
elif (i == "2"):
result = selected(z = config['z'])
return result
The current result is correct, but when I have many cases, I need to hardcode each parameter for the specified function. So, that is why I want to know if it is possible to pass the config object as I want (with an x when i is 0, for example) and then just do something like this:
def a(i: int, config: dict):
function_array = [function1, function2, function3]
result = function_array[i](config)
return result
The syntax for passing items from a dictionary as function parameters is simply selected(**config)
So for your example, it would look something like this:
def function1(x=0):
return x + 1
def function2(y=42):
return y * 2
def function3(z=100):
return z
def a(i, config):
function_array = [function1, function2, function3]
selected = function_array[i]
return selected(**config)
config = {x: 10}
a(0, config) # calls function1(x=10)
config = {y: 20}
a(1, config) # calls function2(y=20)
config = {}
a(2, config) # calls function3()
Every python function can be instructed to take a dictionary of keywords. See e.g. https://www.pythoncheatsheet.org/blog/python-easy-args-kwargs . (Official source at https://docs.python.org/3/reference/compound_stmts.html#function-definitions, but it's harder to read.)
You could do:
def a(i: int, keyword: str, **kwargs: dict):
if keyword in kwargs:
result = kwargs[keyword](i)
and you would run it with something like:
a(5, "func3", func1=print, func2=sum, func3=all)
Or, you could just pass a dictionary itself into the function:
def a(i: int, keyword: str, config: dict)
if keyword in config:
result = config[keyword](i)
This would be run with something like:
a(5, "func3", {"func1": print, "func2": sum, "func3": all})
The only difference is that the ** in the function declaration tells python to automatically make a dictionary out of explicit keywords. In the second example, you make the dictionary by yourself.
There's an important thing happening behind the scenes here. Functions are being passed around just like anything else. In python, functions are still objects. You can pass a function just as easily as you can pass an int. So if you wanted to have a list of lists, where each inner list is a function with some arguments, you easily could:
things_to_do = [[sum, 5, 7, 9], [any, 1, 0], [all, 1, 0]]
for thing_list in things_to_do:
function = thing_list[0]
args = thing_list[1:]
print(function(args))
And you'll get the following results:
21
True
False
(Note also that all of those functions take an iterable, such as a list. If you want to pass each argument separately, you would use *args instead of args.)
You can do it with defined functions, too. If you have
def foo1(arg1):
pass
def foo2(arg1, arg2):
pass
you can just as easily have
things_to_do = [[sum, 5, 7, 9], [foo1, 'a'], [foo2, 0, None]]
I'm new in python programming and would like to seek help in calling a method from another newly modified python file.
I currently have 3 python files: main.py, addBody.py, and originalBody.py.
The addBody will add one segment of the body to originalBody.py in each iteration. This is done by read and write function.
For example,
in the first iteration (initiated from main.py), originalBody.py will look like:
class BODY:
def __init__(self):
object1 = send_cylinder(length = 1.0, radius = 0.1)
bodySegment = {}
bodySegment[0] = 1 #one body
in second iteration, originalBody.py will automatically look like:
class BODY:
def __init__(self):
object1 = send_cylinder(length = 1.0, radius = 0.1)
object2 = send_cylinder(length = 1.0, radius = 0.1)
bodySegment = {}
bodySegment[0] = 1 #one body
bodySegment[1] = 2 #two body
When I'm trying to call the class from main.py,
main.py
from originalBody import BODY
for i in range (0,10):
fileToRead = open('addBody.py')
fileToAppend = open('originalBody.py', 'a')
...(add body from addBody.py to originalBody.py)...
fileToAppend.close()
fileToRead.close()
parent = BODY()
print(parent.bodySegment)
in the first iteration it runs smoothly:
{0: 1}
In the second iteration, after adding the body segment to originalBody.py, supposedly the result is expected to print out:
{0: 1, 1: 2}
However, it prints out the result from the first iteration:
{0: 1}
I suspect that my code calls the function from the original version of originalBody.py that has not modified yet. Do I need to add in some code in my main to get the class method from the modified version of originalBody? Or do I need to add in time delay to call the method right after the modification of originalBody?
You can reload a module when it has already been imported by using the reload builtin function.
I edited your code using import originalBody because I am not sure how the reload function works with the from x import y syntax.
Code below:
from importlib import reload
import originalBody
for i in range (0,10):
reload(originalBody)
fileToRead = open('addBody.py')
fileToAppend = open('originalBody.py', 'a')
...(add body from addBody.py to originalBody.py)...
fileToAppend.close()
fileToRead.close()
parent = originalBody.BODY()
print(parent.bodySegment)