Python小白必学的面向对象

我们已经知道在Python中“一切皆对象”,每个对象都有特定的类型,现在让我们来尝试创建自己的类型——这需要使用class关键字来定义新的“类”(Class),类是用来生成对象的“模板”,对象则是其所属类的“实例”——以下是在交互模式中自定义Thing类,并调用其默认构造器生成一个Thing类的实例对象(注意:自定义类的命名规范要求单词首字母大写):

In [1]: class Thing:
   ...:     """最简单的自定义类"""
   ...: 

In [2]: type(Thing)
Out[2]: type

In [3]: t = Thing()

In [4]: type(t)
Out[4]: __main__.Thing

可以看到,Thing对象属于type类型,是type类的一个实例;t对象属于Thing类型,是Thing类的一个实例——当你在程序中定义自己的类来生成实例对象,就算是“面向对象编程”(Object-Oriented Programming,简称OOP)。面向对象的编程方式使用类来模拟和组织现实世界的事物,可以令程序结构更灵活、条理更清晰。

上面定义的Thing类所生成的实例对象并不能做什么事情,让我们再来创建一个包含了具体子语句的“船”类并生成两个“船”对象:

In [5]: class Ship:
   ...:     """船类"""
   ...:     def __init__(self, name=None):
   ...:         """初始化船实例"""
   ...:         self.name = name  # 船名
   ...:         self.crew = 0  # 船员人数
   ...:     def join(self, number):
   ...:         """船员加入"""
   ...:         self.crew += number
   ...:         return self.crew
   ...:     

In [6]: s1 = Ship("郑和")

In [7]: s1.crew = 200

In [8]: s2 = Ship("戚继光")

In [9]: s2.join(100)
Out[9]: 100

In [10]: s2.crew
Out[10]: 100

Ship类定义了一个特殊的“初始化”方法__init__,这样就能在调用构造器生成实例时加入新的实例“属性”(Property),所谓实例属性就是实例对象的“成员变量”,例如Ship类的实例增加了name和crew属性——从现实概念来理解,任何船都有船名和船员人数这两个数据,但每艘船又有各自的具体数据值。实例属性和实例方法是最常见的两种类成员,Python规定特殊类成员名以两个下划线开始和结束,其他类成员名遵循标准的变量命名规范,注意这里有一个细节概念:作为类成员的__init__属于函数,作为实例成员的__init__则属于方法,在类中定义函数时约定首个参数为“self”,它会指向所生成的实例对象以便操作其成员,对应的实例方法则无此参数,所以调用Ship构造器时只需传入一个参数(也可以不传入任何参数,因为name指定了默认值)。除了实例属性,你也可以定义新的实例方法,让实例能够做更多的事情——例如“船”类还有一个“船员加入”方法。

In [11]: help(Ship)
Help on class Ship in module __main__:

class Ship(builtins.object)
 |  船类
 |  
 |  Methods defined here:
 |  
 |  __init__(self, name=None)
 |      初始化船实例
 |  
 |  join(self, number)
 |      船员加入
 |  
 |  ----------------------------------------------------------------------
 |  Data descriptors defined here:
 |  
 |  __dict__
 |      dictionary for instance variables (if defined)
 |  
 |  __weakref__
 |      list of weak references to the object (if defined)


In [12]: type(Ship.__init__)
Out[12]: function

In [13]: type(s2.__init__)
Out[13]: method

In [14]: s1.__dict__
Out[14]: {'crew': 200, 'name': '郑和'}

实例对象之所以拥有不必自定义而默认存在的特殊成员,是因为面向对象编程的一个重要特性“继承”(Inheritance)——使用继承机制能够将复杂的系统有机地组织起来,所有类都是同一个庞大家族的成员——定义类时可以在类名后加括号指定“基类”,新类将成为其“子类”;如果不指定基类,就默认为最基本的“object”类的子类。子类会继承基类的现有成员,子类定义属性和方法时如果与基类成员同名,就会“覆盖”基类成员。例如下面的程序定义了“船”类及其子类“战舰”类:

"""ship.py 船的家族"""


class Ship:
    """船类"""
    def __init__(self, name=None):
        """初始化船实例"""
        self.name = name  # 船名
        self.crew = 0  # 船员人数

    def join(self, number):
        """船员加入"""
        self.crew += number
        return self.crew


class Warship(Ship):
    """战舰类"""
    def __init__(self, name=None, level=None):
        super().__init__(name)  # 先调用基类初始化方法
        self.level = level  # 舰级


if __name__ == "__main__":
    ws1 = Warship("蓝色空间", "恒星级")
    ws1.join(500)
    print("{}战舰{}号,现有舰员{}人。".format(ws1.level, ws1.name, ws1.crew))

可以注意到Warship类重新定义了__init__,这就会覆盖Ship类中的__init__,所以先调用基类的__init__才能继承到基类定义的实例属性name和crew。

接下来的示例是一个简单的计算器:

"""tkcalc.pyw 简单的计算器
"""
import tkinter as tk


class Calc(tk.Tk):
    """计算器窗体类"""
    def __init__(self):
        """初始化实例"""
        tk.Tk.__init__(self)
        self.title("计算器")
        self.memory = 0  # 暂存数值
        self.create()

    def create(self):
        """创建界面"""
        btn_list = ["C", "M->", "->M", "/",
                    "7", "8", "9", "*",
                    "4", "5", "6", "-",
                    "1", "2", "3", "+",
                    "+/-", "0", ".", "="]
        r = 1
        c = 0
        for b in btn_list:
            self.button = tk.Button(self, text=b, width=5,
                                    command=(lambda x=b: self.click(x)))
            self.button.grid(row=r, column=c, padx=3, pady=6)
            c += 1
            if c > 3:
                c = 0
                r += 1
        self.entry = tk.Entry(self, width=24, borderwidth=2,
                              bg="yellow", font=("Consolas", 12))
        self.entry.grid(row=0, column=0, columnspan=4, padx=8, pady=6)

    def click(self, key):
        """响应按钮"""
        if key == "=":  # 输出结果
            result = eval(self.entry.get())
            self.entry.insert(tk.END, " = " + str(result))
        elif key == "C":  # 清空输入框
            self.entry.delete(0, tk.END)
        elif key == "->M":  # 存入数值
            self.memory = self.entry.get()
            if "=" in self.memory:
                ix = self.memory.find("=")
                self.memory = self.memory[ix + 2:]
            self.title("M=" + self.memory)
        elif key == "M->":  # 取出数值
            if self.memory:
                self.entry.insert(tk.END, self.memory)
        elif key == "+/-":  # 正负翻转
            if "=" in self.entry.get():
                self.entry.delete(0, tk.END)
            elif self.entry.get()[0] == "-":
                self.entry.delete(0)
            else:
                self.entry.insert(0, "-")
        else:  # 其他键
            if "=" in self.entry.get():
                self.entry.delete(0, tk.END)
            self.entry.insert(tk.END, key)


if __name__ == "__main__":
    Calc().mainloop()

53d83e5766128ea75ef83f78749a7b4.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/420583.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Codeforces Round 930 (Div. 2)(A~B)补题

Codeforces Round 930 Div. 2 A. Shuffle Party1、模拟过程2、代码 B. Binary Path1、过程模拟2、代码 A. Shuffle Party A. Shuffle Party A. Shuffle Partytime limit per test: 1 secondmemory limit per test: 256 megabytesinput: standard inputoutput: standard outpu…

2024年3月2日 十二生肖 今日运势

小运播报:2024年3月2日,星期六,农历正月廿二 (甲辰年丙寅月乙丑日),法定节假日。 红榜生肖:鸡、蛇、鼠 需要注意:狗、马、羊 喜神方位:西北方 财神方位:东…

【刷题】位运算

消失的两个数字 消失的两个数字 “单身狗”进阶版思路 class Solution { public:vector<int> missingTwo(vector<int>& nums) {int ret 0;int n nums.size();for(int i 0; i < n; i){ret ^ (nums[i] ^ i);}ret ^ (n ^ (n 1) ^ (n 2));// 按位异或的…

基于SpringBoot的综合小区管理系统的设计与实现

文章目录 项目介绍主要功能截图&#xff1a;部分代码展示设计总结项目获取方式 &#x1f345; 作者主页&#xff1a;超级无敌暴龙战士塔塔开 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题库【关注我&#xff0c;都给你】 &…

Linux 安装k8s

官网 常见的三种安装k8s方式 1.kubeadm 2.kops&#xff1a;自动化集群制备工具 3.kubespray&#xff1a; 提供了 Ansible Playbook 下面以kubeadm安装k8s kubeadm的安装是通过使用动态链接的二进制文件完成的&#xff0c;目标系统需要提供 glibc ##使用 ss 或者 netstat 检测端…

.halo勒索病毒的最新威胁:如何恢复您的数据?

尊敬的读者&#xff1a; 随着科技的发展&#xff0c;网络安全已经成为我们日常生活中不可忽视的重要议题。其中&#xff0c;勒索病毒是当前网络安全威胁中的一大挑战&#xff0c;而“.halo”勒索病毒更是近期备受关注的恶意软件之一。本文将介绍关于“.halo”勒索病毒的背景知…

循环简介和基本运算符

根据C Primer Plus第五章进行学习 文章目录 循环简介基本运算符 1.赋值运算符&#xff1a;2.加法运算符&#xff1a;3.减法运算符&#xff1a;-2.乘法运算符&#xff1a;*总结 1.循环简介 如下代码可以体现不使用循环的局限性&#xff1a; #include<stdio.h> #define AD…

【C语言】linux内核xmit_one函数

一、中文注释 static int xmit_one(struct sk_buff *skb, struct net_device *dev,struct netdev_queue *txq, bool more) {unsigned int len;int rc;// 如果全局ptype列表或者设备特定的ptype列表不为空&#xff0c;则执行网络接口层网络层的NIT&#xff08;Network Tap&…

【C++】vector的使用及其模拟实现

这里写目录标题 一、vector的介绍及使用1. vector的介绍2. 构造函数3. 遍历方式4. 容量操作及空间增长问题5. 增删查改6. vector二维数组 二、vector的模拟实现1. 构造函数2. 迭代器和基本接口3. reserve和resize4. push_back和pop_back5. insert和erase5. 迭代器失效问题5. 浅…

docker 基础(二)

常见命令 Docker最常见的命令就是操作镜像、容器的命令&#xff0c;详见官方文档&#xff1a;https://docs.docker.com/ 数据卷 命令说明文档地址docker volume create创建数据卷docker volume createdocker volume ls创建数据卷docker volume lsdocker volume rm查看所有数…

NGINX 高频面试题及实践总结

NGINX 是一个高性能的开源 Web 服务器和反向代理服务器&#xff0c;被广泛应用于互联网架构中。在面试中&#xff0c;对 NGINX 的相关知识可能会成为考察的重点。下面我们整理了一些常见的 NGINX 面试题及答案&#xff0c;希望对大家在面试前的准备有所帮助。 ## 1. 什么是 NG…

如何系统性的学习推荐系统?

推荐一本适合推荐系统、计算广告、个性化搜索领域的从业人员阅读的书&#xff1a;《互联网大厂推荐算法实战》。快手公司算法专家10余年的实战经验总结。涵盖一线互联网公司当前采用的主流推荐算法&#xff0c;凸显可用性、实用性提供从算法基本原理&#xff0c;到技术框架再到…

python语言1

一、pytho中的注释 1.1注释的理解 程序员在代码中对代码功能解释说明的标注性文字可以提高代码的可读性注释的内容将被python解释器忽略&#xff0c;不被计算机执行 1.2注释的分类 注释分为&#xff1a;单行注释、多行注释、中文声明注释 &#xff08;1&#xff09;单行注…

java项目打包运行报异常:xxxxx-1.0-SNAPSHOT.jar中没有主清单属性

pom.xml中加入这段话即可 <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>2.4.4</version><executions><execution><…

雨云:为你拨开云雾见青天

一、雨云品牌概览 雨云&#xff0c;这名字一听就让人联想到蓝天白云&#xff0c;清爽自然。那么&#xff0c;这个品牌是否真的如其名&#xff0c;能为我们这些在数字世界中漂泊的旅人提供一片宁静、稳定的“云”呢&#xff1f;接下来&#xff0c;让我们深入了解雨云的资质、能…

【Micropython教程】I2C的使用

文章目录 前言一、I2C的使用1.1 分析一种情况1.2 初始化I2C总线1.3 扫描可用的I2C设备1.4 向指定地址写入数据1.5 读取指定地址的数据1.6 关闭I2C总线 二、示例代码总结 前言 MicroPython 是一种精简的 Python 实现&#xff0c;旨在运行在微控制器和嵌入式系统上。在嵌入式开发…

AVL 树

AVL树的概念 二叉搜索树虽可以缩短查找的效率&#xff0c;但如果数据有序或接近有序二叉搜索树将退化为单支树&#xff0c;查找元素相当于在顺序表中搜索元素&#xff0c;效率低下。因此&#xff0c;两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年 发明了一种解决…

vue3的router

需求 路由组件一般放在&#xff0c;pages或views文件夹, 一般组件通常放在component文件夹 路由的2中写法 子路由 其实就是在News组件里面&#xff0c;再定义一个router-view组件 他的子组件&#xff0c;机会渲染在router-view区域 路由传参 <RouterLink :to"/news…

腾讯云最新活动_腾讯云促销优惠_代金券-腾讯云官网入口

腾讯云服务器多少钱一年&#xff1f;62元一年起&#xff0c;2核2G3M配置&#xff0c;腾讯云2核4G5M轻量应用服务器218元一年、756元3年&#xff0c;4核16G12M服务器32元1个月、312元一年&#xff0c;8核32G22M服务器115元1个月、345元3个月&#xff0c;腾讯云服务器网txyfwq.co…

xsslabs第七关

源码 <!DOCTYPE html><!--STATUS OK--><html> <head> <meta http-equiv"content-type" content"text/html;charsetutf-8"> <script> window.alert function() { confirm("完成的不错&#xff01;"…