I am checking a piece of Python code I found online (http://www.exploit-db.com/exploits/18305/), and I'm stuck over a piece of code.
To be honest I don't know Python, but I have experience in other programming languages.
The method _computeCollisionChars generates a number of characters and then adds them to a dictionary if they are different. Below is the method signature along with the relevant part for the question. Note: The actual code can be found on the linked source.
def _computeCollisionChars(self, function, count, charrange):
baseStr = ""
baseHash = function(baseStr) # What is this?
for item in source:
tempStr = ""
if tempStr == baseStr:
continue
if function(tempStr) == baseHash: # What type of comparison is this?
# logic goes here...
return
My questions are:
What does the function parameter mean in the method signature?
Most importantly what does function(string) do? Why are there two
checks, and what sort of output does function(tempStr) generate
then?
Thanks a lot guys!
Apparently you can pass any callable object as function to _computeCollisionChars. Then baseHash is initialised as the result of calling function with an empty string as parameter. Inside the loop, the condition reads: if the result of function called with an empty string as parameter equals the baseHash do this and that. Which is kind of senseless, because tempStr is always '' and baseHash never changes (or you didn't post that part).
In the current snippet the second if is never reached, because invariably tempStr == baseStr == ''.
As the commentors pointed out, in the real code tempStr and baseStr do indeed change and function is expected to be a hashing-function (but any other function which takes a string as argument should work).
In Python functions are first class objects, so they can be passed as arguments to other functions just fine. So function(baseStr) is calling the function object passed to _computeCollisionChars.
Note that Python doesn't check that it is a function object passed as an argument - it just implicitly expects this (and the program would crash it is wasn't, raising a TypeError exception).
>>> def f1():
print "Hello world"
>>> def f2(function):
function()
>>> f2(f1)
Hello World
>>> f2("not a callable function")
TypeError: 'str' object is not callable
Related
I am trying to understand the __str__ method in Python.
class Test:
def __str__(self):
return 5
t = Test()
print(t.__str__())
In this method it returns an integer value but the print method is able to print it.
But, when I tried print(t) it threw the error TypeError: __str__ returned non-string (type int).
As I understand print(t) is also calling the __str__(self) method.
Why didn't print(t.__str__()) want the the string type conversion?
What you’re doing is equivalent to print(5), which works because print calls __str__ on 5 to get a string. But passing the object, print calls __str__ on the object and doesn’t get an actual string in response.
It's all about extra checks that python does with some built-in functions.
len() --> __len__() + some checks
str() --> __str__() + some checks
There is a difference between when "you" call a method explicitly or when that method gets called "by Python"! The point is when Python calls your method it will do some checks for you. (That's one of the reasons that we should use those built-in functions instead of calling relevant dunder method.)
We can see that behavior with len() and __len__() as well:
class Test:
def __len__(self):
return 'foo'
t = Test()
print(t.__len__()) # fine
print(len(t)) # TypeError: 'str' object cannot be interpreted as an integer
So python checked for returning integer in second print statement! that's what expected from __len__().
Same thing happens here. When you call print(t) Python itself calls __str__() method, so it does check to see if __str__() returns a string that is expected or not. (same thing happens with str(t))
But, when you say print(t.__str__()), first, you're calling it's __str__() method on the instance explicitly by yourself, there is no checking here... what does get back ? number 5, and then python will run print(5).
When you call t.__str__() directly it is just like any other method. The method __str__ method was overwritten, so there is nothing special about it when calling it directly.
When doing print(t) invocation happens internally, where some typechecking takes place
if (!PyUnicode_Check(res)) {
_PyErr_Format(tstate, PyExc_TypeError,
"__str__ returned non-string (type %.200s)",
Py_TYPE(res)->tp_name);
Py_DECREF(res);
return NULL;
The manual states:
The return value must be a string object.
so you should do something like
def __str__(self):
return str(5)
or better, something more meaningful like
def __str__(self) -> str:
return "TestObject with id: {}".format(self.id)
(The return type can be added to the function decalaration
so your editor will let you know if it doesn't have the right type.)
When you call print(t), print function tries to get the str(t) value which returns integer. The value has to be str, so it raises an exception. But when you call print(t.__str__()), it doesn't raise an exception because the method acts like an ordinary method and the return value type doesn't have to be str.
I will put here some finding that I found while looking at the behaviour of the print function. So, here goes nothing.
Why didn't print(t.str()) want the the string type conversion?
It actually does (but, I think not the way you expect it). As most people have noted here, what happened with the code, is that it will evaluate the __str__ function first (so, you got the number 5 here). And, what happened is that, it does the conversion (if you look at the source code here) using the __str__ of int class (so, your number 5 will be printed as "5")
But, when I tried print(t) it threw the error TypeError: str returned non-string (type int).
This happen because there is a checking to ensure the object "representated" as string properly. This behaviour can be checked on this source code
In theory, you are correct in this part:
As I understand print(t) is also calling the str(self) method.
Inside Python internal, when calling the __str__ method, Python does call the method __str__(self), but only one time, and it does get the result, a number 5:
https://github.com/python/cpython/blob/3.10/Objects/object.c#L499
But then, Python will check the result in C level, reports an error if the result is not a string:
https://github.com/python/cpython/blob/3.10/Objects/object.c#L505
It will not try to call __str__ method on the result again. So instead see the result, you will get the error TypeError: __str__ returned non-string (type int).
I want to see if a given string is a permutation of a palindrome or not. Here is the python solution. I am trying to test it for the following input example but I am getting error.
import re
class Solution(object):
def isPalindrome(self, s):
regex = re.compile('[^a-zA-Z0-9]')
s=regex.sub('', lower(s))
print(s)
j=len(s)-1
for i in range(0,len(s)/2):
if s[i]==s[j]:
j-=1
else:
return False
return True
# The word is civic , which is a palindrome. So it should return true.
s = "vicic"
print(isPalindrome(s))
I get this error : "NameError: name 'self' is not defined". How can I fix it and print the output?
isPalindrome() as you have defined it here is associated with the object/class Solution.
Unlike a regular Python function your method is called on your solution object.
If you want to call it given your current structure you must first instantiate an instance of solution, create the string you want to test, and then call the method on the object:
sol = Solution() # instance of Solution
s = "vicic"
sol.isPalindrome(s) # False
Also note that I took your string s out from where you had previously declared it as it was in the wrong scope.
In general it seems like your solution class may be a bit of overkill, part of the beauty of Python is its ability to write simple scripts, so you could rewrite isPalindrome() as a plain function and not a method.
So I came across this but don't fully understand why this is the case:
count = 0
Got_one = 0
while(count<1):
print('\n')
response = input("Did you get one?\n:").lower()#<--This part here
if response == 'yes':
Got_one += 1
#...ect
At one point of the script I had typed up .lower without the (). The code ran fine but the script failed to +1 when I inputted "yes", instead it printed out a value of 0, most likely due to the "Got_one" variable being set to 0 in the very beginning. However, as soon as I typed up the () the code worked as intended and +1 to the value after inputting "yes".
So, why is this the case? Is .lower on its own lowering everything after it or just something I don't understand about Python yet?
.lower() is a built-in method for the String object in Python. The reason you need the parenthesis is to execute the function on the string.
Without the parenthesis, you are simply accessing the String.lower attribute, which is a function pointer. Therefore, without the parenthesis, you are setting response = String.lower, which will not pass the if statement.
the difference is that calling it with no parenthesis is your just calling the method but not the value of that method and calling it with parenthesis your calling the value of that method
The reason for that is because .lower() is a class method, not a class attribute (which would be written as .lower).
Therefore, you have to use parenthesis to indicate that you are trying to call a method.
Since it does not take any arguments, you simply only put empty parenthesis behind it.
A class method is a function that belongs to a class object, in this case a str object.
A class attribute is a variable that belongs to this object.
To add to 1313e's answer, .lower() is actually a built-in method (functions for object classes) that you're performing on the string object (because everything in Python is an object), which is why you call 'this string'.lower() and not, say, lower('this string')
This is because you are merely making a reference to the lower class method (function) of the class object str. For reference:
foo = "ALL CAPS"
bar = foo.lower
bar
>>> <built-in method lower of str object at 0x1038e1570>
bar()
>>> 'all caps'
I'm having a bit of an issue when trying to return a function from another file.
main.py:
from master_input import load_input
class Vera(object):
def __init__(self):
masterinput = load_input()
self.masterinput = masterinput
def load_masterinput(self):
return self.masterinput
master_input.py:
import sys
def load_input():
if sys.version_info <= (3,0,0):
masterinput = raw_input()
elif sys.version_info >= (2,7,11):
masterinput = input()
return masterinput
There seems to be no output when running the first file. I want it to return masterinput in the second file because if I were to end the function with load_input(), in the second file, it would just output without even returning self.masterinput in the first file.
You don't show an example of instantiated one of the Vera() options nor to you show any methods that would be using (displaying/printing or otherwise manipulating) this masterinput attribute of your Veta() instance.
So it seems quite likely that your code doesn't seem to be "doing" anything. You'd declared what the objects look like, how to instantiate them and how to respond to a (poorly named) load_masterinput() method call.
Also your module isn't returning a function. When an object is instantiated it, that could will be returning a string, the result of calling either the input() or raw_input() built-in function.
By the way, the smart way, in my opinion, to handle the change from Python2.x raw_input() to Python3 input() is to use code like this:
#!python
if 'raw_input' in dir(__builtins__):
input = raw_input
Note that I'm assigning the function raw_input to the name input ... I'm NOT calling the function and assigning the results of its evaluation here.
Then all my code can use input() and we can forget that the Python2 (evaluated) input() semantics ever existed.
If I want to actually return a function from a function here's one way to do so:
#!python
# filename: my_input.py
def get_input_function():
if 'raw_input' in dir(__builtins__):
# Python2.x and earlier
return raw_input
else:
# Python3
return input
... I would then call this something like so:
#!python
import my_input
input = my_input.get_input_function()
This is unnecessarily obtuse. There's no reason to do something like this for something so trivial. There are cases where you might imagine calling some function, with certain arguments and returning different functions based on those arguments. However, in most cases, you'd still be better off creating a class and instantiating an instance of that.
The problem is that you aren't actually returning the functions, but are instead calling the functions and returning the result. Just remove the parentheses to change the function calls into the functions themselves. I.e., change:
return func()
to:
return func
The return value will then be a callable function.
So basically, let's say you define a function and then write something in () brackets after then function. If I write function(gay), it ends up as 'error name not defined' Python2.73
def lenRecur(aStr):
'''
aStr: a string
returns: int, the length of aStr
'''
print type(aStr)
return
def lenRecur2(aStr):
'''
aStr: a string
returns: int, the length of aStr
'''
s = str(aStr)
print type(s)
return
So when I type lenRecur(gay) or lenRecur2(gay), it ends up as an error whatever I do. So is there a way to avoid it? Without using "" quote marks.
No - unless your input is already a variable that holds a string (or another object).
However, you could use a try-except block (but it won't actually do anything if there's an error).
try:
lenRecur(foo)
lenRecur2(foo)
except NameError:
pass
The error occurs before the function even gets called. Python tries to evaluate the arguments before calling the function. So, Python encounters the bare name gay and wonders, "What the hell is that?"
When it fails to find its value in the local, enclosing, global or builtin scopes, it raises a NameError.
There is no way around this. You must clearly specify what you mean. If gay is a string, you must use quotes.