通过配置文件创建函数实例

发布于 2025-01-11 14:43:08 字数 854 浏览 0 评论 0原文

我们有一个作为字典读取和存储的配置文件,例如

config = {'type': A, 'input': {'color': 'red', 'border': 'thick', 'shape': 'square'}}

现在我们想使用这个配置对象来创建一个类的实例,例如 Drawing_Class ,条件是如果类型是 ' A',颜色始终为蓝色,如果类型为“B”,则形状始终为圆形。

我写了一个函数来实现这一点,这看起来非常不Python,并且想知道是否有更好的方法来实现我的目标?当然,在我给出的示例中,可以只在配置文件中输入所需的颜色和形状,但实际问题更复杂,这是无法实现的。

这是我的功能。

def drawing_dictionary(type):
    if type == 'A':
        value = config['inputs'].pop('color')
        output = drawing_function(**config['inputs'], colour='blue')
        config['input']['color'] = value

    if type == 'B':
        value = config['inputs'].pop('shape')
        output = drawing_function(**config['inputs'], shape='circle')
        config['input']['shape'] = value

    return output

它实现了我需要它实现的目标,即基于此配置文件创建自定义实例,但以一种看起来非常不优雅的方式。非常感谢您的帮助。

We have a configuration file that is read and stored as a dictionary, e.g.

config = {'type': A, 'input': {'color': 'red', 'border': 'thick', 'shape': 'square'}}

Now we want to use this config object to create an instance of a class, say, Drawing_Class with the condition that if the type is 'A', the colour is always blue, and if the type is 'B' the shape is always a circle.

I have written a function to achieve this which seems very unpythonic, and was wondering if there is a better way to achieve my goal? Of course, in the example I've given one could just input the desired colour and shape in the configuration file, but the actual problem is more complex and that can't be achieved.

Here is my function.

def drawing_dictionary(type):
    if type == 'A':
        value = config['inputs'].pop('color')
        output = drawing_function(**config['inputs'], colour='blue')
        config['input']['color'] = value

    if type == 'B':
        value = config['inputs'].pop('shape')
        output = drawing_function(**config['inputs'], shape='circle')
        config['input']['shape'] = value

    return output

It achieves what I need it to achieve, i.e. creating custom instances based on this configuration file, but in a way that seems very inelegant. Help would be much appreciated.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一花一树开 2025-01-18 14:43:08

我喜欢使用 dict 来代替可能很大的 if-elif 块,因此我要做的第一件事是创建类型名称的查找,其中包含字段名称和默认值对于每种类型。

types = {
    "A": ("color", "blue"),
    "B": ("shape", "circle"),
}

我还建议复制配置表的内容,而不是修改它。这可以防止您意外修改它,并且还可以使该函数具有可重入性。这是我的版本:

def drawing_dictionary(typename):
    key, default = types[typename]
    kwargs = config["inputs"].copy()
    kwargs[key] = default
    return drawing_function(**kwargs)

通过此实现,支持新类型就像在 types 中添加一行一样简单,而不是定义新的 if 块。

I like to use dicts to take the place of potentially-large if-elif blocks, so the first thing I would do is to create a lookup for the type names, containing the field name and default value for each type.

types = {
    "A": ("color", "blue"),
    "B": ("shape", "circle"),
}

I would also recommend copying the contents of the config table, rather than modifying it. This will keep you from accidentally modifying it, and also makes the function re-entrant. Here's my version:

def drawing_dictionary(typename):
    key, default = types[typename]
    kwargs = config["inputs"].copy()
    kwargs[key] = default
    return drawing_function(**kwargs)

With this implementation, supporting a new type is as simple as adding a row in types, rather than defining a new if block.

九厘米的零° 2025-01-18 14:43:08

我问了一个关于 Drawing_function 的问题,但我想我应该在答案中写下一些内容并根据需要进行更新。

首先,不要命名变量类型,因为虽然它不是 python 中的保留关键字,但它是一个内置函数,允许您确定对象的类型。

其次,你说你想创建一个函数的实例,你是在谈论函子吗? Drawing_function 是一个类吗?或者您只是根据配置文件调用具有不同参数的函数(这是您的代码似乎表明的内容以及我的假设)?

项目中的其他代码将影响您要使用的参数列表以及您希望如何移动数据以便函数获取正确的参数。您的示例代码看起来像是您已将 config 设置为全局变量,我不推荐这样做。

如果配置文件中有额外的值或缺少值怎么办?你会导致异常,我添加了一个理论验证例程。

对示例代码的一些建议更改:

def drawing_dictionary(config):
    config = validate_config(config) #remove values you don't understand
    #and confirm all the values you need are present set type to 'Error' 
    #if something is wrong
    if config['type'] == 'Error':
        handle_error()#maybe set a default config?
    else: #this assumes you can't fix the config
        return drawing_function(**config['inputs'],config_type=config['type'])

    return some_sort_of_error_value_or_throw_exception

在 Drawing_function 内部,您将解压 config['inputs'] 中的所有值,这样您将拥有一个名为 color 的变量和一个名为 shape 的变量,然后您可以在该函数中按类型处理更改确保它总是发生并且不更改配置字典:

if config_type == 'A':
    colour = 'blue'
elif config_type == 'B':
    shape = 'circle'

您还可以将 if elif 内容替换为 火柴盒如果您使用的是 python 3.10 或更高版本,请声明

I asked a question about drawing_function but figured I'd put some things down in an answer and update as necessary.

First off do not name a variable type as while it isn't a reserved keyword in python it is a built in function that allows you to determine the type of an object.

Second you say you want to create an instance of a function, are you talking about a functor? Is drawing_function a class? or are you just calling a function with different arguments depending on a config file (this is what your code seems to indicate and what I have assumed)?

The other code in your project will have an impact on the argument list you want to use and how you want to move data around so that the function gets the correct arguments. Your example code looks like you've made config a global variable which I would not recommend.

What if the config file has extra values in it or is missing values? You'd cause an exception I've added a theoretical validation routine.

Some recommended changes to your example code:

def drawing_dictionary(config):
    config = validate_config(config) #remove values you don't understand
    #and confirm all the values you need are present set type to 'Error' 
    #if something is wrong
    if config['type'] == 'Error':
        handle_error()#maybe set a default config?
    else: #this assumes you can't fix the config
        return drawing_function(**config['inputs'],config_type=config['type'])

    return some_sort_of_error_value_or_throw_exception

inside of drawing_function you will have all the values in the config['inputs'] unpacked so you'll have a variable named colour and one names shape then you can handle the changes by type in that function to ensure it always happens and without changing the config dictionary:

if config_type == 'A':
    colour = 'blue'
elif config_type == 'B':
    shape = 'circle'

You could also swap out the if elif stuff for a match case statement if you're using python 3.10 or newer.

你的背包 2025-01-18 14:43:08

看来您有一个具有全局配置的配置层次结构“if A then color=blue, if B then shape= Circle”优先于配置文件。这样的层次结构可以借助 collections.ChainMap 进行建模,请参见以下示例:

from collections import ChainMap


GLOBAL_CONFIG = {
    'A': dict(color='blue'),
    'B': dict(shape='circle'),
}


def drawing_dictionary(config):
    return drawing_function(**ChainMap(
        GLOBAL_CONFIG.get(config['type'], {}),
        config['input'],
    ))


def drawing_function(**kwargs):
    import pprint
    pprint.pprint(kwargs)


drawing_dictionary({'type': 'A', 'input': {'color': 'red', 'border': 'thick', 'shape': 'square'}})
drawing_dictionary({'type': 'B', 'input': {'color': 'red', 'border': 'thick', 'shape': 'square'}})

It seems that you have a hierarchy of configurations with the global configuration "if A then color=blue, if B then shape=circle" taking precedence over the configuration file. Such a hierarchy can be modeled with the help of collections.ChainMap, see the following example:

from collections import ChainMap


GLOBAL_CONFIG = {
    'A': dict(color='blue'),
    'B': dict(shape='circle'),
}


def drawing_dictionary(config):
    return drawing_function(**ChainMap(
        GLOBAL_CONFIG.get(config['type'], {}),
        config['input'],
    ))


def drawing_function(**kwargs):
    import pprint
    pprint.pprint(kwargs)


drawing_dictionary({'type': 'A', 'input': {'color': 'red', 'border': 'thick', 'shape': 'square'}})
drawing_dictionary({'type': 'B', 'input': {'color': 'red', 'border': 'thick', 'shape': 'square'}})
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文