What is the Ruby String sub function? - python

I'm trying to convert a Ruby script into a Python script (having absolutely no understanding of the various functions in Ruby) and can't find anything on the Ruby sub function.
Here's the function I'm trying to translate:
def getCCache(arg1, arg2, arg3)
local4 = Digest::MD5.hexdigest(arg1 + arg2)
local5 = 0
while (local5 < arg3.length)
temp1 = arg3[local5]
temp2 = local5
local5 += local5;
local4.sub(temp1, arg3[temp2])
local5 += 1
end
return (local4)
end
The line I'm having trouble with is local4.sub(temp1, arg3[temp2]). What does the sub function do? If there's an equivalent in Python I would appreciate that as well.

local4.sub(temp1, arg3[temp2])
does nothing. It returns a copy of the string local4 with the first occurance of the substring referenced by temp1 substituted by the second argument. Then the result is discarded : no variable is assigned to the result.
local4 = local4.sub(temp1, arg3[temp2]) #or
local4.sub!(temp1, arg3[temp2])
would both do string substitution.

sub(pattern) {|...| block } → $_
Equivalent to $_.sub(args), except that $_ will be updated if substitution occurs. Available only when -p/-n command line option specified.
$_ is a ruby global variable and it represents string last read by gets

Related

eval after exec: seemingly same strings do not provide the same result (may be encoding problem)

I defined the _exec_ function for getting the output of a function represented by a string.
For instance the sgn function evaluated with the arg value (see code below).
Then I will have to perform a single eval in the end.
(Warning: exec or eval of unknown code must be secured before use.)
def _exec_(thecode):
local = {}
exec(thecode, globals(), local)
return local["_output_"]
sgn = "\nif _input_[0]<0:\n _output_ = -1\nif _input_[0]==0:\n _output_ = 0\nif _input_[0]>0:\n _output_ = 1"
arg = "[5]"
code_list = ["_input_ = "+arg+sgn]
print(eval("1+_exec_(code_list[0])"))
The last 2 lines provide the good result.
However I will have to use it for an undetermined number of times with various "string-functions" and "string-arguments".
Is it possible to do it with only 1 named string instead of a list of strings?
I tried:
code = "1+_exec_(_input_ = "+arg+sgn+")"
print(eval(code))
which lead to SyntaxError: invalid syntax.
Maybe the encoding of special characters is wrong, then I tried:
code = "1+_exec_(_input_ = "+arg+sgn.encode('unicode-escape').decode()+")"
print(eval(code))
which lead to SyntaxError: unexpected character after line continuation character.
I also tried to use the answer to Python: exec() a code block and eval() the last line, without success.
They aren't the same strings, "seemingly" or otherwise. Just take the eval out of both print(eval(...)) calls and compare:
>>> print("1+_exec_(code_list[0])")
1+_exec_(code_list[0])
vs:
>>> code = "1+_exec_(_input_ = "+arg+sgn+")"
>>> print(code)
1+_exec_(_input_ = [5]
if _input_[0]<0:
_output_ = -1
if _input_[0]==0:
_output_ = 0
if _input_[0]>0:
_output_ = 1)
That latter one doesn't look anything like something that might be expected to be valid syntax.

How can I tell my function to do something specific thing when it receives no parameters?

So, I have the following function which should resemble the already implemented " print " function in Python. ( I know it is silly to make a function that only uses a pre-defined function but I am practicing with different things ) The thing that I want to do with my function is: make it act the same as the pre-defined one. That is, when the print function is called with no parameters, I would like it to print an empty line just as " print() " does. How do i do that ?
def print_str( string, how_many_times, tail ):
print ( string * how_many_times, end = tail )
print doesn't take a single string, it takes 0 or most strings as argument. end has a reasonable default. You can imagine a (simplified) definition of
def print(*args, end='\n'):
...
You need to do the same for yours. A reasonable default for how_many_times would be 1. If you don't want print_str to take multiple arguments, "" would be a reasonable default for string.
def print_str(string="", how_many_times=1, tail='\n'):
print(string * how_many_times, end=tail)
You can do something like this:
def myfunc(a=None):
if a == None:
print()
else:
print("hi")
If no arguments are presented it prints nothing, but if an argument is given it prints 'hi'.

How to extract a function given by a content string in Python

I have a content of a function given by a string. I'm looking for a way how to convert this string into a function object to call it.
content = "def my_function(x):\n return x**2"
my_function = extract_function_from_string(content) # extract_function_from_string ???
print my_function(5) # prints 25
Perhaps, there's a way to convert the string into a python module and extract the function from it
If you know the function name, you can run exec on the string. Eval will not work as it only targets expressions. See \r\n vs \n in python eval function. If you don't know the function name, but all your function have the same format you can try something like this:
def extract_function_from_string(content):
exec(content)
start = 4
end = content.find("(")
function_name = content[start:end]
return eval(function_name)
my_function = extract_function_from_string("def my_function(x):\n return x**2")
print my_function(5)
The train has left the safe and sound python station a long time ago, but I guess this is just a curiosity.
You can use exec
>>>content = "def my_function(x):\n return x**2"
>>>exec content
>>>my_function(5)
25
For Python 3.x
>>>exec(content)
Try the exec statement:
>>> content = "def my_function(x):\n return x**2"
>>> exec content
>>> my_function(5)
25
Here is something that does not leave safe train of python completely.
def extract_function_from_string(content, function_index=0):
import ast
tree = ast.parse(content, mode='exec')
function = tree.body[function_index]
module = ast.Module([function])
exec(compile(module, filename="<ast>", mode='exec'))
return locals()[function.name]
content = "def my_function(x):\n return x**2"
my_function = extract_function_from_string(content) # extract_function_from_string ???
print(my_function(5)) # prints 25
You can use the eval function to do this. e.g. eval("print('Hello')").
However, do be advised that this can be a security risk, and there is probably a better way of doing it than parsing a string.
a = "lambda x:x**2"
my_func = eval(a)
print my_func(3)

splitting up strings to x amount of characters

I am trying to make a decrypter that decrypts code from the encrypter I made. I am getting this type error when I run the code though
getcrypt = ''.join(map(Decrypt.get,split_up_into_sixteen_chars(x_str)))
TypeError: split_up_into_sixteen_cjars() takes 0 positional arguments but 1 was given
I'm fairly new to programming and not sure whats causing this.
heres my code
Decrypt = {'1s25FF5ML10IF7aC' : 'A', 1s2afF5ML10I7ac' : 'a'} #I obviously have more than this but I'm trying to make it as simplified as possible
def split_up_into_sixteen_chars():
while len(x_str)>0:
v = x_str[:16]
print(v)
x_str = (input())
getcrypt = ''.join(map(Decrypt.get,split_up_into_sixteen_chars(x_str)))
print(getcrypt)
You have defined a function that takes no parameters:
def split_up_into_sixteen_chars():
yet you are passing it one:
split_up_into_sixteen_chars(x_str)
You need to tell Python that the function takes one parameter here, and name it:
def split_up_into_sixteen_chars(x_str):
The name used does not have to match the name that you pass in for the function call, but it does have to match what you use inside the function. The following function would also work; all I did was rename the parameter:
def split_up_into_sixteen_chars(some_string):
while len(some_string) > 0:
v = some_string[:16]
print(v)
This works because the parameter some_string becomes a local name, local to the function. It only exists inside of the function, and is gone again once the function completes.
Note that your function creates an infinite loop; the length of some_string will either always be 0, or always be longer than 0. The length does not change in the body of the loop.
The following would work better:
def split_up_into_sixteen_chars(some_string):
while len(some_string) > 0:
v = some_string[:16]
print(v)
some_string = some_string[16:]
because then we replace some_string with a shorter version of itself each time.
Your next problem is that the function doesn't return anything; Python then takes a default return value of None. Printing is something else entirely, print() writes the data to your console or IDE, but the caller of the function does not get to read that information.
In this case, you really want a generator function, and use yield. Generator functions return information in chunks; you can ask a generator for the next chunk one by one, and that is exactly what map() would do. Change the function to:
def split_up_into_sixteen_chars(some_string):
while len(some_string) > 0:
v = some_string[:16]
yield v
some_string = some_string[16:]
or even:
def split_up_into_sixteen_chars(some_string):
while some_string:
yield some_string[:16]
some_string = some_string[16:]
because an empty string is 'false-y' when it comes to boolean tests as used by while and if.
As your map(Decrypt.get, ...) stands, if split_up_into_sixteen_chars() yields anything that is not present as a key in Dycrypt, a None is produced (the default value for dict.get() if the key is not there), and ''.join() won't like that. The latter method can only handle strings.
One option would be to return a string default instead:
''.join(map(lambda chunk: Decrypt.get(chunk, ''), split_up_into_sixteen_chars(x_str)))
Now '', the empty string, is returned for chunks that are not present in Decrypt. This makes the whole script work for whatever string input you have:
>>> x_str='Hello world!'
>>> ''.join(map(lambda chunk: Decrypt.get(chunk, ''), split_up_into_sixteen_chars(x_str)))
''
>>> x_str = '1s25FF5ML10IF7aC'
>>> ''.join(map(lambda chunk: Decrypt.get(chunk, ''), split_up_into_sixteen_chars(x_str)))
'A'

The Matlab equivalent of Python's "None"

Is there a keyword in Matlab that is roughly equivalent to None in python?
I am trying to use it to mark an optional argument to a function. I am translating the following Python code
def f(x,y=None):
if y == None:
return g(x)
else:
return h(x,y)
into Matlab
function rtrn = f(x,y)
if y == []:
rtrn = g(x);
else
rtrn = h(x,y);
end;
end
As you can see currently I am using [] as None. Is there a better way to do this?
in your specific case. you may use nargin to determine how many input arguments here provided when calling the function.
from the MATLAB documentation:
The nargin and nargout functions
enable you to determine how many input
and output arguments a function is
called with. You can then use
conditional statements to perform
different tasks depending on the
number of arguments. For example,
function c = testarg1(a, b)
if (nargin == 1)
c = a .^ 2;
elseif (nargin == 2)
c = a + b;
end
Given a single input argument, this
function squares the input value.
Given two inputs, it adds them
together.
NaN while not equivalent, often serves the similar purpose.
nargin is definitely the easiest way of doing it. Also it is usually good practice to validate the number of input argument using nargchk:
function e = testFunc(a,b,c,d)
error( nargchk(2, 4, nargin, 'struct') );
% set default values
if nargin<4, d = 0; end
if nargin<3, c = 0; end
% ..
c = a*b + c*d;
end
... which acts as a way to ensure the correct number of arguments is passed. In this case, a minimum of two arguments are required, with a maximum of four.
If nargchk detects no error, execution resumes normally, otherwise an error is generated. For example, calling testFunc(1) generates:
Not enough input arguments.
UPDATE: A new function was introduced in R2011b narginchk, which replaces the use of the deprecated nargchk+error seen above:
narginchk(2,4);
You can use functions like: exist and isempty to check whether a variable exists and whether it is empty respectively:
if ~exist('c','var') || isempty(c)
c = 10;
end
which allows you to call your function such as: testFunc(1,2,[],4) telling it to use the default value for c but still giving a value for d
You could also use varargin to accept a variable number of arguments.
Finally a powerful way to parse and validate named inputs is to use inputParser
To see examples and other alternatives of passing arguments and setting default values, check out this post and its comments as well.
The equivalent to Python None in MATLAB is string(missing)
To test, type the following in your command window : py.type( string(missing) )
It returns <class 'NoneType'>
MATLAB to python data types documentation here
If you want to pass None into a Python function that you are calling from MATLAB, then you would pass in string(missing). This argument would show up as None in the Python function, for example, if you are detecting for None such as if arg1 == None.

Categories

Resources