I would like to call a function with another function as argument, which is not yet defined and callable. Is there a pythonic way how to do this?
I know that you can give a function as an argument for another function, like this answer suggests:
Python function as a function argument?
But this somehow is not possible for functions which are not yet defined and callable.
I wrote a lot of those repetitive code recently and I'm pretty sure there must be a more pythonic way to do this.
Repetitive code:
import pymysql
def database_connection():
return pymysql.connect(db="MyDatabase", user='root', host="127.0.0.1", password="SecretPassword")
def mysql_request_true(sql_text):
connection = database_connection()
try:
with connection.cursor() as cursor:
cursor.execute(sql_text)
result = True
connection.commit()
return result
except ConnectionError:
return False
finally:
connection.close()
def mysql_request_database_id(sql_text):
connection = database_connection()
try:
with connection.cursor() as cursor:
cursor.execute(sql_text)
result = cursor.lastrowid
connection.commit()
return result
except ConnectionError:
return False
finally:
connection.close()
def mysql_request_fetchone(sql_text):
connection = database_connection()
try:
with connection.cursor() as cursor:
cursor.execute(sql_text)
result = cursor.fetchone()
connection.commit()
return result
except ConnectionError:
return False
finally:
connection.close()
def mysql_request_fetchall(sql_text):
connection = database_connection()
try:
with connection.cursor() as cursor:
cursor.execute(sql_text)
result = cursor.fetchall()
connection.commit()
return result
except ConnectionError:
return False
finally:
connection.close()
What I try to achieve:
import pymysql
def database_connection():
return pymysql.connect(db="MyDatabase", user='root', host="127.0.0.1", password="SecretPassword")
def mysql_request(sql_text, cmd):
connection = database_connection()
try:
with connection.cursor() as cursor:
cursor.execute(sql_text)
result = cmd
connection.commit()
return result
except ConnectionError:
return False
finally:
connection.close()
def mysql_request_true(sql_text):
return mysql_request(sql_text, True)
def mysql_request_database_id(sql_text):
return mysql_request(sql_text, cmd=cursor.lastrowid)
def mysql_request_fetchone(sql_text):
return mysql_request(sql_text, cmd=cursor.fetchone())
def mysql_request_fetchall(sql_text):
return mysql_request(sql_text, cmd=cursor.fetchall())
The code sample above does not work, because cursor is not yet defined when I give it as an argument.
Does anybody know how to do this? Thank you very much for your answers.
So I think the issue you might have is that you need a cursor for each function, but do not want to repeat the call to create a cursor each time. One way to counteract this would be a wrapper function which provided a cursor:
from functools import wraps
def with_cursor(func):
@wraps(func)
def decorator_function(self, *args, **kwargs):
cursor = connection.cursor()
context = func(self, cursor, *args, **kwargs)
cursor.close()
return context
return decorator_function
In this way, each function takes cursor as the first argument, but can then be sure it is available.
You can defer resolving the function's name with simple lambda
:
def my_func(param, cmd=lambda: this_is_not_yet_defined_fn):
print(cmd()(param))
this_is_not_yet_defined_fn = sum
my_func([1, 2])
Prints:
3
I think you can get the desired behavior using lambda
. Just pass a function extracting the desired feature of cursor
as an argument to you mysql_request
function as such:
def mysql_request(sql_text, cmd):
connection = database_connection()
try:
with connection.cursor() as cursor:
cursor.execute(sql_text)
result = cmd(cursor) # Call cmd which extracts the desired information
connection.commit()
return result
except ConnectionError:
return False
finally:
connection.close()
Then you can pass the cmd
argument as a lambda function:
def mysql_request_true(sql_text):
return mysql_request(sql_text, lambda cursor:True)
def mysql_request_database_id(sql_text):
return mysql_request(sql_text, lambda cursor:cursor.lastrowid)
def mysql_request_fetchone(sql_text):
return mysql_request(sql_text, lambda cursor:cursor.fetchone())
def mysql_request_fetchall(sql_text):
return mysql_request(sql_text, lambda cursor:cursor.fetchall())
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.