Code notes: Explaining the what is happening in the code [duplicate] - python

This question already has answers here:
What does Python's eval() do?
(12 answers)
Closed 4 years ago.
I am a newbie developer. I have used the code below but I would like to understand how the last line works, can someone please explain to me the last line return eval(((str(a)+"*")*b)[:-1]) of the code?
def power(a,b):
if b == 0:
return 1
else:
return eval(((str(a)+"*")*b)[:-1])

eval evaluates python code or lets Python program run Python code within itself.
example:
CODE:
a = 15
eval('print(a + 3)')
OUTPUT:
18
when you return the following
eval(((str(a)+"*")*b)[:-1])
what you basically doing is this( for example if you are computing power(2,5)):
str(a) -> changes the value of a to string. in this case "2"
str(a)+"*" -> concatinate the above string to the multiplication sign. now we have "2*"
(str(a)+"*")*b) -> duplicates the above string b times. That is "2*"+"2*"+"2*"+"2*"+"2*", that is five times and now you have "2*2*2*2*2*"
But as you can see there is an extra "*" at the end. To remove this one we use [:-1]. what this basically doing is select all except the last one. ":" basically means all.
so the final expression to be evaluated is "2*2*2*2*2". which is 2^5.

The best way is to use a**b for computing power. However, if you want to use eval then consider joining the string in this way: eval('*'.join(str(a)*b)). In this, str(a) will convert integer a to string a then *b will repeat the a b times and finally the '*'.join() will join all the a's together with * in between and create a string something like a*a*a*a. eval will then evaluate the string as if it is an expression.

return eval(((str(a)+"*")*b)[:-1])
is equivalent to
a_str=str(a) # convert a in STRING
a_star=a_str+"*" # concat the string a_str with "*"
a_repeted=a_star*b # repeat a_star "b" times
exp=(a_repeted)[:-1] # get all a_repeted car except the last on (ex 3*3*3*3 for a=3 and b=4)
res=eval(exp) # evalutate the expression
return res
it'is equivalent to (really better ;-) !) :
def power(a,b):
return a ** b

A terrible idea, as others have said - if you're a newbie, consider finding a better guide!
eval reads a string and evaluates it as if it were not (as if it is not in quotes). So we construct a string of a ** b (ie a^b), and ask Python to read it, then return all but the last character. Pretty pointless but there you go.

eval() is never a good idea to use. Read about its dangerous behaviour here.
You just need ** operator which is equivalent to ^ (raise to) operator you see in other languages:
def power(a,b):
return a ** b

Related

How to format Python code to always return this specific length [duplicate]

This question already has answers here:
Dynamically calculated zero padding in format string in python
(2 answers)
How do I pad a string with zeroes?
(19 answers)
Closed 9 months ago.
Sorry if this is a bit of a noob question. But moving on..
Say at the beginning of my code I set a variable, like this:
TestVar = 'A6'
But I later want it to print out as 000000A6
Or say it was
TestVar = 'C30'
I'd want it to print out as 00000C30
Basically always returning it with a length of 8
The reasoning for this is I've made a general script for modding a game, (I can link if asked) and you need to put in certain values which I want to have format automatically for ease of use. For example on running it'll print
Item ID Here:
And if you put in 166 it would convert the decimal number to hex which would be A6, however in order to be usable for all values (not just ones that are 2 digits once converted) I'm trying to make it detect it's length and format it with the 0s before.
Sorry if this doesnt make sense, in a simpler way of saying this, is there a way for it to detect the length of a variable? So for example in pseudo
TestVar = 'C30'
If TestVar length = 3
print('00000'+TestVar)
Print Result: 00000C30
Basically always returning it with a length of 8
That's what format strings do:
>>> print(f"{'C30':>08s}")
00000C30
As a sidenote, to output any number as 8-digit hex:
>>> print(f"{100:>08X}")
00000064
>>> print(f"{1024:>08X}")
00000400
See the documentation:
for f-strings (the f'I am an f-string' syntax);
for formatting syntax (the >08s and >08X thing).
Use string function rjust():
print(test.rjust(8,'0'))
The .zfill string method can be used.
For example:
s = 'C30'
s.zfill(8)
>>> '00000C30'
Try this code
txt = "A6"
x = txt.zfill(8)
print(x)
You can use string.zfill method
for example.
code = '3C0'
filledCode = code.zfill(8)
this method filled with zero the number of digit that you pass like a parameter
try something like this str.rjust() function
i = 1111
pad = '0'
n = 8
x = str(i).rjust(n, pad)
print(x) # 00001111

Finding the length of first half of a string using string slicing in Python?

I'm working on an assignment in PyCharm, and have been tasked with the following problem:
The len() function is used to count how many characters a string contains. Get the first half of the string storied in the variable 'phrase'.
Note: Remember about type conversion.
Here's my code so far that it's given me:
phrase = """
It is a really long string
triple-quoted strings are used
to define multi-line strings
"""
first_half = len(phrase)
print(first_half)
I have no idea what to do. I need to use string slicing to find the first half of the string "phrase". Any help appreciated. I apologize for my ignorance.
Just slice the first half of the string, be sure to use // in the event that the string is of odd length like:
print phrase[:len(phrase) // 2] # notice the whitespace in your literal triple quote
Try something like:
first_half = len(phrase)
print(phrase[0:first_half/2])
It will need to be smarter to handle strings of odd length. See this question for more on slicing.
first_half = phrase[:len(phrase)//2] or phrase[:int(len(phrase)/2)]
Note: Remember about type conversion.
In Python 2 the division will yield an int, however in Python 3 you want to use an int division like this half = len(phrase) // 2
Below is a Python 2 version
>>> half = len(phrase) / 2
>>> phrase[:half]
'\nIt is a really long string\ntriple-quoted st'
No need for the 0 in phrase[0:half], phrase[:half] looks better :)
Try this print(string[:int(len(string)/2)])
len(string)/2 returns a decimal normally so that's why I used int()
Use slicing and bit shifting (which will be faster should you have to do this many times):
>>> s = "This is a string with an arbitrary length"
>>> half = len(s) >> 1
>>> s[:half]
'This is a string wit'
>>> s[half:]
'h an arbitrary length'
Try this:
phrase = """
It is a really long string
triple-quoted strings are used
to define multi-line strings
"""
first_half = phrase[0: len(phrase) // 2]
print(first_half)
you can simply slicing a string using it's indexes.
For Example:
def first_half(str):
return str[:len(str)/2]
The above function first_half accept a string and return it's half using slicing

Concatenate string and int in Python 3 .4 [duplicate]

This question already has an answer here:
How can I concatenate str and int objects?
(1 answer)
Closed 1 year ago.
I'm new to Python, so I've been running through my own set of exercises to simply start memorizing basic functions and syntax.
I'm using the PyCharm IDE and Python 3.4. I've run into an issue when running through some basic string and integer concatenation exercises. Each instance below is throwing an unsupported operand type. There are several threads on Stack Overflow that clearly states proper concatenation syntax, but the above error message continues to plague me.
print ("Type string: ") + str(123)
print ("Concatenate strings and ints "), 10
In Python 3+, print is a function, so it must be called with its arguments between parentheses. So looking at your example:
print ("Type string: ") + str(123)
It's actually the same as:
var = print("Type string: ")
var + str(123)
Since print returns nothing (in Python, this means None), this is the equivalent of:
None + str(123)
which evidently will give an error.
That being said about what you tried to do, what you want do to is very easy: pass the print function what you mean to print, which can be done in various ways:
print ("Type string: " + str(123))
# Using format method to generate a string with the desired contents
print ("Type string: {}".format(123))
# Using Python3's implicit concatenation of its arguments, does not work the same in Python2:
print ("Type string:", str(123)) # Notice this will insert a space between the parameters
Note that print is a function in Python 3. In Python 2, your first line would concatenate "Type string: " and "123" and then print them. In Python 3, you are calling the print function with one argument, which returns None, and then add "123" to it. That doesn't make any sense.
The second line doesn't generate an error in Python 2 or 3 (I've tested it with 2.7.7 and 3.2.3). In Python 2, you get
Concatenate strings and ints 10
while in Python 3, your script should only print
Concatenate strings and ints
This is because again, print is a function, and therefore you call it with the argument "Concatenate strings and ints". The , 10 makes your line a tuple of the return value of print, which is None, and 10. Since you don't use that tuple for anything, there is no visible effect.
Try format():
print("Type string: {}".format(123))
print("Concatenate strings and ints {}".format(10))
There is nothing wrong with this:
print ("Type string: ") + str(123)
print is just a function like anything else. And you're calling that function with one argument, "Type string: ", and then trying to add the result (which will be None) to the string '123'. That isn't going to work. If you wanted to add the two strings together, you have to put them into the same expression, inside the parentheses:
print("Type string: " + str(123))
Similarly:
print ("Concatenate strings and ints "), 10
This calls print with one argument, and then makes a tuple of the None returned by print and the number 10. If you want to pass 10 to the print call, it has to go inside the parentheses:
print("Concatenate strings and ints ", 10)
As gitaarik's answer points out, using str.format is more flexible, and avoids the possibility of problems like this. It also gives you code that works exactly the same way in both Python 2.6-2.7 and Python 3.x, which is pretty nice even if you aren't trying to write dual-platform/single-codebase code, because it'll be understandable even to people who only know one or the other.
I think this is a pretty cool way to concatenate a string and an int in Python:
print (f"Type string: {123}")
print (f"Concatenate strings and ints {10}")
You can do it like this:
c = 'Emerson'
d = 32
print("My name is %s and I am %d years old." %(c,d))
Result:
My name is Emerson and I am 32 years old.

Better way to evaluate mathematical expression in python? [duplicate]

This question already has answers here:
Evaluating a mathematical expression in a string
(14 answers)
Closed 9 years ago.
Say I have 50,000 lines of string that contain simple mathematical expression (only +,- operator involve e.g. 1+2+3+5). I know that it is handy to use eval() in Python to evaluate those strings. However, the program is not efficient enough. I ran the cProfile and found most of the bottleneck is from the eval function (around 2.5 secs in 50,000 lines case). I've tried to write my own evaluation parser but it perform even slower then the eval.
So, what I want to ask is if there are any way to fast evaluate mathematical expression strings or improve the performance of eval()? Third-party package cannot be used.
The original problem is like this
We have a string of digit like 1234567 and we can insert +,-,or nothing between the digits like 1+23-4+56-7. So there will be 3^(digit-1) combinations for a given number string
What I implement in Python to calculate and generate string like the following
import itertools
def gen_Eq(op, num):
temp = [None]*(2*len(num)-1)
temp[::2] = num
temp[1::2] = op
string = ''.join(temp)
return string
def cal_Eq(num_string):
op_list = tuple(itertools.product(['+','-',''],repeat=len(num_string)-1))
eq = list(map(gen_Eq,op_list,itertools.repeat(num_string,len(op_list))))
print map(eval,eq)
This approach is faster:
>>> import re
>>> split_numbers = re.compile(r'-?\d+').findall
>>> sum(int(x) for x in split_numbers('1+23-4+56-7'))
69
In my timings the sum expression takes 4.5 µs vs. 13 µs for eval('1+23-4+56-7')
Note, however, that it does not handle consecutive + and -, eg. 1-+2 or 1--2, or spaces: 1 - 2.

python cyclic shifting of the characters in the string

Subclass sstr of the standard str type that implements the "<<" and ">>" methods as a cyclic shifting of the characters in the string.What trying to do is
>>> s1 = sstr("abcde")
>>> s1 << 0
'abcde'
>>> s1 >> 0
'abcde'
>>> s1 << 2
'cdeab'
>>> s1 >> 2
'deabc'
>>> s1 >> 5
'abcde'
# my attempt:
import string
class sstr(str):
def __new__(self, other):
return str.__new__(self, other.upper())
def __ilshift__(self, other):
return str.__ilshift(other)
def __rshift__(self, other):
return str.__rshift(other)
This smells like homework, so I'm not going to post actual code here. But to help, I will point out flaws I see in your code and an algorithm:
My python 2.7.2 reports no __ilshift or __irshift in str. Also, if you are trying to shift a string by a certain number of characters, then you shouldn't be shifting the variable you call other. You should be shifting self by other many characters. That being said, you're probably better off naming other as n or some such.
Now, I assume you know how circular shifting is supposed to work. The examples you provide get the message across well.
As a simple algorithm (easy to read/understand), try this (pseudo-code follows):
function __ilshift(self, n) { // self is the string to be shifted. n denotes how many characters to shift it by
answer = copy()
for i = 1 to n {
answer = self[1:] //answer = everything in self excluding the first character
answer += self[0] // append the first character of self to answer
}
return answer
}
The above solution would work. Though, it is quite inefficient. We know that when an n-character string is shifted by n, the result of the shifting is the string itself. When you think about this a little more, you realize that you end up shifting by n % lengthOfSelf. Thus, the for i = 1 to n turns into for i = 1 to n%len(self).
Still, we can make this more efficient. To do this would require splicing self at the appropriate index, which I'll let you figure out, because I think this is homework.
Hope this gets you closer!
s1 << 0
This calls __lshift__, not __ilshift__. The i stands for in-place; you can't change a string in-place anyway, and aren't trying to here (you're trying to create a new value).
The problem with your actual code is that you're trying to implement the shift by just calling the base str class's shift. But the base str class doesn't have that shift operation - that's the entire reason you have this exercise!
Hint: put together two slices of the string. 'foobar' << 2 is 'obar' + 'fo'. Can you see how to slice the string to get those? How do the numbers you use for the slices relate to the number specified for shifting?

Categories

Resources