【问题标题】:How to give a Python function a function as an argument which is not yet callable?如何给 Python 函数一个函数作为参数,但它还不能被调用?
【发布时间】:2019-11-04 10:32:39
【问题描述】:

我想以另一个函数作为参数调用一个函数,该函数尚未定义和可调用。有没有一种pythonic方法可以做到这一点?

我知道您可以将一个函数作为另一个函数的参数,就像这个答案所暗示的那样:

Python function as a function argument?

但这对于尚未定义和可调用的函数来说是不可能的。

我最近写了很多重复的代码,我很确定一定有一种更 Python 的方式来做到这一点。

重复代码:

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()

我想达到的目标:

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())

上面的代码示例不起作用,因为当我将光标作为参数给出时,它还没有定义。

有人知道怎么做吗?非常感谢您的回答。

【问题讨论】:

  • 一种方法是使用一个字典,其中键是字符串,值是函数。然后将命令作为字符串传递,并在字典中找到要调用的相应函数。

标签: python python-3.x function


【解决方案1】:

所以我认为您可能遇到的问题是每个函数都需要一个游标,但不想每次都重复调用来创建游标。解决此问题的一种方法是提供一个游标的包装函数:

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

这样,每个函数都将光标作为第一个参数,但可以确定它是可用的。

【讨论】:

    【解决方案2】:

    您可以使用简单的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])
    

    打印:

    3
    

    【讨论】:

      【解决方案3】:

      我认为您可以使用lambda 获得所需的行为。只需将提取cursor 所需特征的函数作为参数传递给mysql_request 函数,如下所示:

      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()
      

      然后您可以将 cmd 参数作为 lambda 函数传递:

      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())
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-03-18
        • 2013-11-19
        • 2019-12-16
        • 1970-01-01
        • 1970-01-01
        • 2022-11-12
        • 1970-01-01
        • 2018-10-29
        相关资源
        最近更新 更多