python 类中定义类

Here’s a neat Python trick you might just find useful one day. Let’s look at how you can dynamically define classes, and create instances of them as required.

这是一个整洁的Python技巧,有一天可能会有用。 让我们看一下如何动态定义类,并根据需要创建它们的实例。

This trick makes use of Python’s object oriented programming (OOP) capabilities, so we’ll review those first.

该技巧将利用Python的面向对象编程(OOP)功能,因此我们将首先对其进行回顾。

类和对象 (Classes and objects)

Python is an object-oriented language, meaning it lets you write code in the object oriented paradigm.

Python是一种面向对象的语言,这意味着它使您可以使用面向对象的范例编写代码。

The key concept in this programming paradigm is classes. In Python, these are used to create objects which can have attributes.

该编程范例中的关键概念是类。 在Python中,这些用于创建可以具有属性的对象。

Objects are specific instances of a class. A class is essentially a blueprint of what an object is and how it should behave.

对象是类的特定实例。 类本质上是什么是对象以及其行为的蓝图。

Classes are defined with two types of attribute:

类用两种类型的属性定义:

  • Data attributes — variables available to a given instance of that class

    数据属性 -该类的给定实例可用的变量

  • Methods — functions available to an instance of that class

    方法 -该类实例可用的函数

The classic OOP example usually involves different types of animal, or food. Here, I’ve gone more practical with a simple data visualization theme.

典型的OOP示例通常涉及不同类型的动物或食物。 在这里,我通过一个简单的数据可视化主题变得更加实用。

First, define the class BarChart.

首先,定义类BarChart

class BarChart:def __init__(self, title, data):self.title = titleself.data = datadef plot(self):print("\n"+self.title)for k in self.data.keys():print("-"*self.data[k]+" "+k)

The __init__ method lets you set attributes upon instantiation. That is, when you create a new instance of BarChart, you can pass arguments that provide the chart’s title and data.

__init__方法使您可以在实例化时设置属性。 也就是说,当您创建BarChart的新实例时,可以传递提供图表标题和数据的参数。

This class also has a plot() method. This prints a very basic bar chart to the console when it is called. It could feasibly do more interesting things in a real application.

此类还具有plot()方法。 调用时,这会将非常基本的条形图打印到控制台。 它可以在实际的应用程序中做更多有趣的事情。

Next, instantiate an instance of BarChart:

接下来,实例化BarChart的实例:

data = {"a":4, "b":7, "c":8}bar = BarChart("A Simple Chart", data)

Now you can use the bar object in the rest of your code:

现在,您可以在其余的代码中使用bar对象:

bar.data['d'] = bar.plot()
A Simple Chart
---- a
------- b
-------- c
----- d

This is great, because it allows you to define a class and create instances dynamically. You can spin up instances of other bar charts in one line of code.

这很棒,因为它允许您定义一个类并动态创建实例。 您可以在一行代码中旋转其他条形图的实例。

new_data = {"x":1, "y":2, "z":3}
bar2 = BarChart("Another Chart", new_data)
bar2.plot()
Another Chart
- x
-- y
--- z

Say you wanted to define several classes of chart. Inheritance lets you define classes which “inherit” properties from base classes.

假设您要定义几类图表。 继承使您可以定义从基类“继承”属性的类。

For example, you could define a base Chart class. Then you can define derived classes which inherit from the base.

例如,您可以定义一个基础Chart类。 然后,您可以定义从基类继承的派生类。

class Chart:def __init__(self, title, data):self.title = titleself.data = datadef plot(self):pass
class BarChart(Chart):def plot(self):print("\n"+self.title)for k in self.data.keys():print("-"*self.data[k]+" "+k)
class Scatter(Chart):def plot(self):points = zip(data['x'],data['y'])y = max(self.data['y'])+1x = max(self.data['x'])+1print("\n"+self.title)for i in range(y,-1,-1):line = str(i)+"|"for j in range(x):if (j,i) in points:line += "X"else:line += " "print(line)

Here, the Chart class is a base class. The BarChart and Scatter classes inherit the __init__() method from Chart. But they have their own plot() methods which override the one defined in Chart.

在这里, Chart类是基类。 BarChartScatter类从Chart.继承__init__()方法Chart. 但是它们有自己的plot()方法,这些方法将覆盖Chart定义的方法

Now you can create scatter chart objects as well.

现在,您还可以创建散点图对象。

data = {'x':[1,2,4,5], 'y':[1,2,3,4]}
scatter = Scatter('Scatter Chart', data)
scatter.plot()
Scatter Chart
4|     X
3|    X
2|  X
1| X
0|

This approach lets you write more abstract code, giving your application greater flexibility. Having blueprints to create countless variations of the same general object will save you unnecessarily repeating lines of code. It can also make your application code easier to understand.

这种方法使您可以编写更多的抽象代码,从而为应用程序提供更大的灵活性。 使用蓝图来创建同一通用对象的无数变体将节省您不必要的重复代码行。 它还可以使您的应用程序代码更易于理解。

You can also import classes into future projects, if you want to reuse them at a later time.

如果您希望以后再使用它们,则也可以将类导入将来的项目中。

工厂方法 (Factory methods)

Sometimes, you won’t know the specific class you want to implement before runtime. For example, perhaps the objects you create will depend on user input, or the results of another process with a variable outcome.

有时,您在运行时之前不知道要实现的特定类。 例如,您创建的对象可能取决于用户输入,或者取决于具有可变结果的另一个过程的结果。

Factory methods offer a solution. These are methods that take a dynamic list of arguments and return an object. The arguments supplied determine the class of the object that is returned.

工厂方法提供了解决方案。 这些方法采用动态参数列表并返回一个对象。 提供的参数确定返回的对象的类。

A simple example is illustrated below. This factory can return either a bar chart or a scatter plot object, depending on the style argument it receives. A smarter factory method could even guess the best class to use, by looking at the structure of the data argument.

下面说明一个简单的示例。 该工厂可以根据收到的style参数返回条形图或散点图对象。 通过查看data参数的结构,更聪明的工厂方法甚至可以猜测要使用的最佳类。

def chart_factory(title, data, style):if style == "bar":return BarChart(title, data)if style == "scatter":return Scatter(title, data)else:raise Exception("Unrecognized chart style.")
chart = chart_factory("New Chart", data, "bar")
chart.plot()

Factory methods are great when you know in advance which classes you want to return, and the conditions under which they are returned.

如果事先知道要返回哪些类以及它们返回的条件,则工厂方法非常有用。

But what if you don’t even know this in advance?

但是,如果您甚至不事先知道该怎么办?

动态定义 (Dynamic definitions)

Python lets you define classes dynamically, and instantiate objects with them as required.

Python使您可以动态定义类,并根据需要使用它们实例化对象。

Why might you want to do this? The short answer is yet more abstraction.

您为什么要这样做? 简短的答案是更多抽象。

Admittedly, needing to write code at this level of abstraction is generally a rare occurrence. As always when programming, you should consider if there is an easier solution.

诚然,在这种抽象级别上编写代码通常很少见。 与往常一样,在编程时,应考虑是否有更简单的解决方案。

However, there may be times when it genuinely proves useful to define classes dynamically. We’ll cover a possible use-case below.

但是,有时确实证明动态定义类很有用。 我们将在下面介绍一个可能的用例。

You may be familiar with Python’s type() function. With one argument, it simply returns the “type” of the object of the argument.

您可能熟悉Python的type()函数。 对于一个参数,它仅返回参数对象的“类型”。

type(1) # <type 'int'>
type('hello') # <type 'str'>
type(True) # <type 'bool'>

But, with three arguments, type() returns a whole new type object. This is equivalent to defining a new class.

但是,使用三个参数, type()返回一个全新的object类型 。 这等效于定义一个新类 。

NewClass = type('NewClass', (object,), {})
  • The first argument is a string that gives the new class a name第一个参数是为新类命名的字符串
  • The next is a tuple, which contains any base classes the new class should inherit from接下来是一个元组,其中包含新类应继承的所有基类
  • The final argument is a dictionary of attributes specific to this class最后一个参数是特定于此类的属性的字典

When might you need to use something as abstract as this? Consider the following example.

您何时需要使用这种抽象的东西? 考虑以下示例。

Flask Table is a Python library that generates syntax for HTML tables. It can be installed via the pip package manager.

Flask Table是一个Python库,可为HTML表生成语法。 可以通过pip软件包管理器进行安装。

You can use Flask Table to define classes for each table you want to generate. You define a class that inherits from a base Table class. Its attributes are column objects, which are instances of the Col class.

您可以使用Flask Table为要生成的每个表定义类。 您定义一个从基本Table类继承的类。 它的属性是列对象,它们是Col类的实例。

from flask_table import Table, Col
class MonthlyDownloads(Table):month = Col('Month')downloads = Col('Downloads')data = [{'month':'Jun', 'downloads':700},{'month':'Jul', 'downloads':900},{'month':'Aug', 'downloads':1600},{'month':'Sep', 'downloads':1900},{'month':'Oct', 'downloads':2200}]table = MonthlyDownloads(data)print(table.__html__())

You then create an instance of the class, passing in the data you want to display. The __html__() method generates the required HTML.

然后,您创建该类的实例,并传入要显示的数据。 __html__()方法生成所需HTML。

Now, say you’re developing a tool that uses Flask Table to generate HTML tables based on a user-provided config file. You don’t know in advance how many columns the user wants to define — it could be one, it could be a hundred! How can your code define the right class for the job?

现在,假设您正在开发一个使用Flask Table来基于用户提供的配置文件生成HTML表的工具。 您事先不知道用户要定义多少列-可以是一列,也可以是一百列! 您的代码如何为工作定义合适的类?

Dynamic class definition is useful here. For each class you wish to define, you can dynamically build the attributes dictionary.

动态类定义在这里很有用。 对于要定义的每个类,可以动态构建attributes字典。

Say your user config is a CSV file, with the following structure:

假设您的用户配置是CSV文件,其结构如下:

Table1, column1, column2, column3
Table2, column1
Table3, column1, column2

You could read the CSV file line-by-line, using the first element of each row as the name of each table class. The remaining elements in that row would be used to define Col objects for that table class. These are added to an attributes dictionary, which is built up iteratively.

您可以使用每一行的第一个元素作为每个表类的名称逐行读取CSV文件。 该行中的其余元素将用于定义该表类的Col对象。 这些被添加到attributes字典中,该字典是迭代建立的。

for row in csv_file:attributes = {}for column in row[1:]:attributes[column] = Col(column)globals()[row[0]] = type(row[0], (Table,), attributes)

The code above defines classes for each of the tables in the CSV config file. Each class is added to the globals dictionary.

上面的代码为CSV配置文件中的每个表定义了类。 每个类都添加到globals字典中。

Of course, this is a relatively trivial example. FlaskTable is capable of generating much more sophisticated tables. A real life use-case would make better use of this! But, hopefully, you’ve seen how dynamic class definition might prove useful in some contexts.

当然,这是一个相对琐碎的例子。 FlaskTable能够生成更为复杂的表。 一个现实的用例将更好地利用这一点! 但是,希望您已经看到动态类定义在某些情况下可能会很有用。

所以现在你知道了... (So now you know…)

If you are new to Python, then it is worth getting up to speed with classes and objects early on. Try implementing them in your next learning project. Or, browse open source projects on Github to see how other developers make use of them.

如果您是Python的新手,那么值得早日熟悉类和对象。 尝试在下一个学习项目中实施它们。 或者, 在Github上浏览开源项目,以了解其他开发人员如何利用它们。

For those with a little more experience, it can be very rewarding to learn how things work “behind-the-scenes”. Browsing the official docs can be illuminating!

对于那些有更多经验的人来说,学习事物在幕后的工作方式可能是非常有益的。 浏览官方文档可能会很有启发!

Have you ever found a use-case for dynamic class definition in Python? If so, it’d be great to share it in the responses below.

您是否曾经在Python中找到动态类定义的用例? 如果是这样,最好在下面的回复中分享。

翻译自: https://www.freecodecamp.org/news/dynamic-class-definition-in-python-3e6f7d20a381/

python 类中定义类

python 类中定义类_Python中的动态类定义相关推荐

  1. python类和对象介绍_python中的类,对象,方法,属性等介绍

    注:这篇文章写得很好.加底纹的是我自己的理解 python中一切皆为对象,所谓对象:我自己就是一个对象,我玩的电脑就是对象,坐着的椅子就是对象,家里养的小狗也是一个对象...... 我们通过描述属性( ...

  2. python中类的属性一般来说_python中实例属性和类属性之间的关系

    匿名用户 1级 2018-06-25 回答 一般来说,在Python中,类实例属性的访问规则算是比较直观的. 但是,仍然存在一些不是很直观的地方,特别是对C++和Java程序员来说,更是如此. 在这里 ...

  3. python的类中包含什么_Python中的类(中)

    上一篇介绍了Python中类相关的一些基本点,本文看看Python中类的继承和__slots__属性. 继承 在Python中,同时支持单继承与多继承,一般语法如下: classSubClassNam ...

  4. python 类中静态变量_Python中的类或静态变量

    python 类中静态变量 Python类/静态变量 (Python Class / Static Variables) Class or Static variables are class-rel ...

  5. python中的类是什么意思_python中什么是类

    面向对象最重要的概念就是类(Class)和实例(Instance),必须牢记类是抽象的模板,比如Student类,而实例是根据类创建出来的一个个具体的"对象",每个对象都拥有相同的 ...

  6. python中定义数据结构_Python中的数据结构—简介

    python中定义数据结构 You have multiples algorithms, the steps of which require fetching the smallest value ...

  7. python怎样定义数组_python中定义数组的正确方法

    我的模拟器(c++)使用python作为绑定. 在我的c++中,我定义数组如下 这是我的变量声明(在头中)Ptr m_names [2]; 这是我的函数声明(在头中) ^{pr2}$ 在源文件中voi ...

  8. python中函数的定义包括_python中函数的定义及调用

    python中函数的定义及使用方法 1.函数的概念:函数是将具有独立功能的代码块组织为一个整体,使其具有特殊功能的代码集; 2.函数的作用:使用函数可以加强代码的复用性,提高程序编写的效率; 3.函数 ...

  9. python中的常量_Python中的变量和常量

    本文主要介绍Python中的变量和常量,包括变量的命名规范,使用注意事项 -------------- 完美的分割线 --------------- 1.变量 1.1.变量理解 1)什么是变量 变量即 ...

  10. python实例化是什么意思_Python中实例化class的执行顺序示例详解

    前言 本文主要介绍了关于Python实例化class的执行顺序的相关内容,下面话不多说了,来一起看看详细的介绍吧 Python里对类的实例化时有怎样的顺序 一般来说一个类里面有类变量和方法,比如我们定 ...

最新文章

  1. nginx 代理 内存_科普Nginx和apache的区别及优缺点比较
  2. python用途与前景-Python 未来发展前景怎么样?
  3. Vue学习【第六篇】:Vue-cli脚手架(框架)与实战案例
  4. Spring Cloud-鸿鹄Cloud分布式微服务云系统—架构图
  5. c# 按位与,按位或
  6. Abp 0.18.0 正式发布! -ABP CLI,新模板和其他功能
  7. Java 中的日期与时间
  8. 谈表达式树的缓存(6):五种缓存方式的性能比较
  9. POJ 2955 Brackets(区间DP)
  10. linux查看schema版本,Schema 日期
  11. flash builder4.6 集成svn1.8报错
  12. 微信公众号开发之分享功能
  13. 用极限定义证明微积分基本定理
  14. Java基础之成员变量与局部变量
  15. leetcode | 回文数
  16. 想要玩转数字影音?可以找Adobe帮忙呀
  17. 无法登录QQ和wegame,连接超时
  18. javascript tree
  19. Cuckoo Sandbox
  20. HarmonyOS——一个面向物联网的操作系统

热门文章

  1. 使用mybatis一次性添加多条数据 在oracle 数据库上
  2. CentOS 7 相关命令
  3. 快速学习 async await 的使用, Demo 解析
  4. iOS自定义转场动画
  5. Python中处理时间 —— time模块
  6. Ubuntu安装Anaconda
  7. Linux账户安全管理--useradd、groupadd、passwd、chown、chmod工具
  8. 详解使用DockerHub官方的mysql镜像生成容器
  9. 细说Debug和Release区别
  10. 虚拟化--006 VCAC的sso配置成功