当前位置: 首页 > 编程日记 > 正文

python 类中定义类_Python中的动态类定义

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 类中定义类

相关文章:

用自定义方法,传入成绩数组,实现输出考试成绩的成三名

package com.imooc; import java.util.Arrays; //导入Array类包 import java.util.Scanner; //导入Scanner类包 public class Final2 { public static void main(String args[]){Scanner…

EJS 什么是EJS后缀文件 EJS怎么用

一、什么是EJS EJS是一个JavaScript模板库&#xff0c;用来从JSON数据中生成HTML字符串。 二、为什么要使用EJS 与最初的JavaScript相比较&#xff0c;一些不太了解你的代码的人可以更容易地通过EJS模板代码看得懂你的代码。 让我们放松一下&#xff0c;一起来享受下令人激动的…

一个推荐系统,实现完整的设计-在百度搜索关键词推荐案例

在之前一篇博文中&#xff0c; 有同学在评论中问了个问题&#xff1a; 怎样解决因式分解带来的推荐冷门。热门关键词的问题。 在回答这个问题的时候&#xff0c; 想到了近几年在做搜索推荐系统的过程中&#xff0c; 学术界和工业界的一些差别。 正好近期正在做技术规划&#xf…

如何充分利用JavaScript(ES6)中的解构功能

by Joanna Gaudyn乔安娜高登(Joanna Gaudyn) Destructuring was a new addition to ES6. It took inspiration from languages like Python and allows you to extract data from arrays and objects into distinct variables. It might sound like something you’ve done in…

React 开发环境搭建

先来一个 React 官方文档的链接 点击跳转 搭建 React 的前期准备&#xff1a;你的本地环境需要安装 cnpm、node。 注&#xff1a;代码块中的 $ 代表&#xff1a; $后面是在命令行输入的命令&#xff0c;举例 $ npm start 解&#xff1a;实际上是应该打开命令行输入 npm st…

c++中的友元重载

1 语法 返回值类型 operator 运算符名称(形参列表) { 重载实体 } --------->operator和运算符名称在一起构造成新的函数名 2 案例 1 #include <iostream>2 3 using namespace std;4 5 class Complex6 {7 public:8 9 Complex(float x0,float y0) 10 :_…

WPF解析TTF 字体

偶遇需要自己解析 TTF 字体并显示&#xff0c;此做。。。 using System; using System.Collections.Generic; using System.Drawing.Text; using System.IO; using System.Linq; using System.Runtime.Serialization; using System.Text; using System.Windows; using System.W…

redux logic_Redux-Logic简介

redux logicby Sam Ollason通过萨姆奥拉森(Sam Ollason) Redux-Logic简介 (An Introduction to Redux-Logic) This article will go through a high-level overview of Redux-Logic. We will look at what is it, why it is needed, how it differs from other Redux middlewa…

[SDOI2009]HH的项链

题目背景 无 题目描述 HH 有一串由各种漂亮的贝壳组成的项链。HH 相信不同的贝壳会带来好运&#xff0c;所以每次散步完后&#xff0c;他都会随意取出一段贝壳&#xff0c;思考它们所表达的含义。HH 不断地收集新的贝壳&#xff0c;因此&#xff0c;他的项链变得越来越长。有一…

DvaJS 入门, 快速上手Dva

为什么要使用Dva? React 没有解决的问题 React 本身只是一个 DOM 的抽象层&#xff0c;使用组件构建虚拟 DOM。 如果开发大应用&#xff0c;还需要解决一个问题。 通信&#xff1a;组件之间如何通信&#xff1f;数据流&#xff1a;数据如何和视图串联起来&#xff1f;路由…

Static、DynamicResource学习笔记一

定义了资源后&#xff0c;我们可以在元素中直接使用该资源&#xff0c;但又分为StaticResource及DynamicResource两种方式。 StaticResource 静态资源在首次创建窗口时一次性的设置完毕&#xff0c;之后源资源对象本身发生的任何变化都会影响到使用该资源的元素&#xff0c;如果…

javascript迭代器_JavaScript迭代器概述

javascript迭代器by Joanna Gaudyn乔安娜高登(Joanna Gaudyn) JavaScript迭代器概述 (An overview of JavaScript iterators) for&#xff0c;for…in和for…of循环之间的区别 (The difference between for, for…in and for…of loops) Iteration might be one of the most c…

knockout学习笔记目录

关于knockout学习系列的文章已经写完&#xff0c;这里主要是做个总结&#xff0c;并且将目录罗列出来&#xff0c;方便查看。欢迎各位大神拍砖和讨论。 总结 kncokout是一个轻量级的UI类库&#xff0c;通过MVVM模式使前端的UI简单话&#xff0c;减少javascript代码的编写。通常…

ant Design Pro 登录状态管理

未登录自动跳转到登录页面&#xff0c;登录成功不跳转回登录页面的实现代码调用流程。 ant Design Pro 是一个企业中后台管理框架&#xff0c;开始做他&#xff0c;第一个肯定是要做登录&#xff0c;下面来看一下它是怎么登录的。 先看路由配置 Authorized.jsx代码&#xff1…

初级java开发学习路线_成为初级全栈Web开发人员的10分钟路线图

初级java开发学习路线So you have started your journey into the world of web development. But what do you learn first? The Internet is overloaded with a wealth of information about the millions of different technologies that a web developer can know.因此&am…

国外物联网平台初探(四):Ayla Networks

定位 Ayla企业软件解决方案为全球部署互联产品提供强大的工具 功能 Ayla的IoT平台包含3个主要组成部分&#xff1a; (1) Ayla嵌入式代理Ayla Embedded Agents (2) Ayla云服务Ayla Cloud Services (3) Ayla应用库Ayla Application Libraries 设备 开发者使用任何微控制器、操作系…

《英语语法新思维初级教程》学习笔记(一)名词短语

参考资料&#xff1a; 1. 《英语语法新思维初级教程》 ▶ 知识点 ▼ 英语是“固定词序语言&#xff08;a fixed-word-order language&#xff09;”。 ▼ 语言的构造级别分五个层次&#xff1a;1. 词&#xff08;word&#xff09;&#xff1b;2. 短语&#xff08;phase&#xf…

根据数组中对象的属性值排序倒叙

数组中对象的属性值排序倒叙demo function compare(e) {return function (a, b) {var value1 a[e];var value2 b[e];return parseInt(value1) - parseInt(value2);} } var arr[{a:2},{a:3},{a:1}];var arr2 arr.sort(compare(time)).reverse();console.log(arr2) //[{a:3}…

!! javascript_产量! 产量! 生成器如何在JavaScript中工作。

!! javascriptby Ashay Mandwarya ?️??由Ashay Mandwarya提供吗&#xff1f; 产量&#xff01; 产量&#xff01; 生成器如何在JavaScript中工作。 (Yield! Yield! How Generators work in JavaScript.) If the title doesn’t already give a hint, we will be discussin…

ACM 竞赛高校联盟 练习赛 第二场 BC

B. 题解&#xff1a; 枚举约数即可&#xff0c;判断n个数能否填约数的整数倍 #include <iostream> #include <cstring> #include <cstdio> using namespace std; typedef long long LL; int main(){LL T, n, m;cin>>T;while(T--){cin>>n>>…

在一个数组中查找两个重复出现的数字

题目如下&#xff1a;现有一个数组长度为n1&#xff0c;里面存放有1到n-2&#xff0c;顺序不定&#xff0c;其中有两个数字出现了两次&#xff0c;现在要找出那两个数字。 例子A{2, 3, 1, 4, 5, 2, 4}&#xff0c; 这个数组长度为7&#xff0c;存放了1到5&#xff0c;但2和4出现…

React 组件生命周期

组件的生命周期可分成三个状态&#xff1a; Mounting&#xff1a;已插入真实 DOMUpdating&#xff1a;正在被重新渲染Unmounting&#xff1a;已移出真实 DOM 生命周期的方法有&#xff1a; componentWillMount 在渲染前调用,在客户端也在服务端。 componentDidMount : 在第一…

银行软件开发实习生_如何找到学生的软件开发人员实习生

银行软件开发实习生by Grazietta Hof由Grazietta Hof 如何找到学生的软件开发人员实习生 (How to find a Software Developer Internship as a student) Side note: Although this article is directed at students (because I am one so I can easily relate), I’m sure a l…

MAC OS X El CAPITAN 搭建SPRING MVC (1)- 目录、包名、创建web.xml

一、 下载STS&#xff08;Spring Tool Suite&#xff09; 官方地址&#xff1a;http://spring.io/tools/sts 下载spring tool suite for mac 最新版本。这个IDE是很不错的&#xff0c;其中spring插件已经配置好了。下载解压缩&#xff08;一定要英文目录下&#xff09;&#xf…

iOS小知识点记录

1>UITextField实现leftView: self.inputTextField [[UITextField alloc]initWithFrame:CGRectMake(10, 10, 200, 25)];self.inputTextField.delegate self;self.inputTextField.font [UIFont systemFontOfSize:15];self.inputTextField.placeholder " 想说点什么?…

Ant Design Pro 网络请求,视图绑定model并且渲染到页面 umi-request

封装网络请求,在service中新建接口,在model调用service,在视图绑定model并且得到网络请求的回调函数,获取网络请求的数据渲染到页面。 网络请求数据走向; 1.在utils/request.js 封装网络请求; /*** request 网络请求工具* 更详细的 api 文档: https://github.com/umijs…

2019机器学习比赛_2019顶尖的机器学习课程

2019机器学习比赛With strong roots in statistics, Machine Learning is becoming one of the most interesting and fast-paced computer science fields to work in. There’s an endless supply of industries and applications machine learning can be applied to to mak…

HTML5 canvas画图

HTML5 canvas画图 HTML5 <canvas> 标签用于绘制图像&#xff08;通过脚本&#xff0c;通常是 JavaScript&#xff09;。不过&#xff0c;<canvas> 元素本身并没有绘制能力&#xff08;它仅仅是图形的容器&#xff09; - 您必须使用脚本来完成实际的绘图任务。getCo…

排序算法7---快速排序算法

原理&#xff1a; 通过一趟排序将待排记录分割成独立的两部分&#xff0c;其中一部分记录的关键字均比另一部分记录的关键字小&#xff0c;则可分别对这两部分记录继续进行排序&#xff0c;以达到整个序列有序的目的。 #include <stdio.h> #define MAXSIZE 9typedef stru…

dispatch callback ant design pro 网络请求回调函数

index.jsx 代码解析:在组件初次渲染时调用 model 中 命名空间为 a_models 的 getData 网络请求,传了一个patload 参数和 callback 回调函数过去,然后通过 this.setState ()更新视图的 state。 import { Form, Tabs,Affix, Button,Input,Table } from antd; import Re…