在Python中以动态字符串的形式创建一个给定类名的对象

在Python中以动态字符串的形式创建一个给定类名的对象,python,methods,arguments,Python,Methods,Arguments,假设我有两门课: tables.py class Device79table(tables.Table): class Meta: #link to datasource model = Device79 attrs = {"class": "paleblue"} models.py class Device79(models.Model): # data for table 我有一个引用这两个类的函数 views.py

假设我有两门课:

tables.py

class Device79table(tables.Table):
    class Meta:
        #link to datasource
        model = Device79
        attrs = {"class": "paleblue"} 
models.py

class Device79(models.Model):
    # data for table  
我有一个引用这两个类的函数

views.py

def function():
    #makes table of all objects in device 79
    table = Device79table(Device79.objects.all()) 
    table.draw() 
有可能这样做吗?假设参数“device”=Device79

def function(device)
    table = device+table(device.objects.all())
    table.draw() 

这是基于设备值绘制的表。也就是说,设备可以是设备79、设备80、设备81等。。程序会自动绘制正确的表格

我不知道
Device79table
是在哪里定义的,但我假设它是
global

我对它的虚假定义:

def Device79Table(arg):
    print arg
将其与您的功能相结合:

def function(device):
    globals()[device + 'table'](device.objects.all())
    table.draw()

globals()
函数返回所有全局对象的
dict
,其中键包含其名称的字符串。因此
globals()

这是一个新的解决方案,它考虑到这样一个事实,即您实际上并没有实例化类,而是直接使用类对象

由于
Device79
必须在
Device79table.Meta
之前定义,因此您无法告诉
Device79
在其自身定义期间使用哪个表。您甚至不能在
Device79table
期间执行此操作,因为它还不存在

因此,在定义相应的表之后,您需要告诉设备79使用哪个表

如您所见,我也选择不使用动态变量名,而是在另一个变量中使用一个明确定义的对象。动态变量名使代码更难阅读和维护

型号.py

class Device79(models.Model):
    table = None  # Optional, but cleaner.
import models

class Device79table(tables.Table):
    class Meta:
        # link to datasource
        model = models.Device79
        attrs = {"class": "paleblue"} 

# once the table is defined, we can tell Device79 which table to use.
models.Device79.table = Device79table
import tables  # "from tables import Device79table" would work too.
from models import Device79
# You need to import tables, even if you access the tables from the models,
# because this is where we tell the device which table to use.

def function(device)
    table = device.table(device.objects.all())
    table.draw() 

function(Device79)
表格.py

class Device79(models.Model):
    table = None  # Optional, but cleaner.
import models

class Device79table(tables.Table):
    class Meta:
        # link to datasource
        model = models.Device79
        attrs = {"class": "paleblue"} 

# once the table is defined, we can tell Device79 which table to use.
models.Device79.table = Device79table
import tables  # "from tables import Device79table" would work too.
from models import Device79
# You need to import tables, even if you access the tables from the models,
# because this is where we tell the device which table to use.

def function(device)
    table = device.table(device.objects.all())
    table.draw() 

function(Device79)
视图.py

class Device79(models.Model):
    table = None  # Optional, but cleaner.
import models

class Device79table(tables.Table):
    class Meta:
        # link to datasource
        model = models.Device79
        attrs = {"class": "paleblue"} 

# once the table is defined, we can tell Device79 which table to use.
models.Device79.table = Device79table
import tables  # "from tables import Device79table" would work too.
from models import Device79
# You need to import tables, even if you access the tables from the models,
# because this is where we tell the device which table to use.

def function(device)
    table = device.table(device.objects.all())
    table.draw() 

function(Device79)
通常,循环导入不是问题,只要您导入模块而不是单个对象,但由于您需要在表定义期间直接访问模型,因此无法在
models.py
中导入表。这就是为什么我们在
tables.py
中更改设备以告诉它使用哪个表,而不是在
models.py
中直接设置它

这样,我们保持导入链如下:
视图->表->模型
模型
从不尝试导入
,但这也意味着我们必须在某个地方至少导入一次
,以完成模型定义


这有点令人惊讶,但我想不出一种更干净、更简单的方法来实现这一点,而只处理类对象而不处理实例。

Python在反射方面尤其出色。根据您的描述,下面是一个您可以做的示例:

models.py中

class Device79:
    objects = "Device79.objects"
class Device79table:
    def __init__(self, devices):
        self.devices = devices

    def draw(self):
        print "%s.draw() called with %s" % (self.__class__, self.devices)
import tables

def function(device):
    table = tables.__dict__[device.__name__ + 'table'](device.objects)
    table.draw()

import models
function(models.Device79)
tables.py中

class Device79:
    objects = "Device79.objects"
class Device79table:
    def __init__(self, devices):
        self.devices = devices

    def draw(self):
        print "%s.draw() called with %s" % (self.__class__, self.devices)
import tables

def function(device):
    table = tables.__dict__[device.__name__ + 'table'](device.objects)
    table.draw()

import models
function(models.Device79)
然后在
views.py
中:

class Device79:
    objects = "Device79.objects"
class Device79table:
    def __init__(self, devices):
        self.devices = devices

    def draw(self):
        print "%s.draw() called with %s" % (self.__class__, self.devices)
import tables

def function(device):
    table = tables.__dict__[device.__name__ + 'table'](device.objects)
    table.draw()

import models
function(models.Device79)
或者:

from models import Device79
function(Device79)

这是可能的,但可能不是你想做的。你有没有考虑过为所有
设备*表
对象制作
dict
?嘿@mhlester,我没有,但是你知道这类问题是什么,这样我就可以通过谷歌更好地了解问题了吗?我会在这段时间做个口述,干杯!我决定把它作为一个答案。见下文@Fury,非常感谢你的回答!我更新了我的问题,因为我忘了提到一些信息。我试过你的方法,结果是循环导入。你认为你能把我推向正确的方向吗?:)我没有意识到您实际上是在处理类对象,而不是这些类的实例。这使得循环导入无法解决(通常情况下,循环导入并不是一个真正的问题。但对你来说,这是一个问题。我找到了一个解决方案,我会更新我的答案。嗨@mhlester,非常感谢你的回答!我更新了我的问题,因为我忘了提到几个关键信息。我认为你的解决方案可能仍然适用,但我不能100%确定只要所有设备都可用以相同的方式定义,它仍应适用。请尝试!