Python基础(7)——类和对象(一)
类和对象(一)
- 1. 基本概念
- 2. 类的定义和实例化
- 3. 类中的属性和方法
- 3.1 属性
- 3.1.1 类属性
- 3.1.2 实例属性
- 3.2 方法
- 3.3 类的特殊方法
- 3.3.1 常用特殊方法
- 3.3.2 实现迭代器常用特殊方法
- 3.3.3 运算符重载的特殊方法
- 3.3.4 比较运算符重载的方法
- 3.3.5 与单目运算符相关的特殊方法
- 3.3.6 与类型转换相关的特殊方法
- 3.3.7 与常见内建函数相关的特殊方法
- 4. 类的特性
- 4.1 封装
- 4.2 继承
- 4.2.1 单继承
- 4.2.2 多继承
- 4.3 多态
Python
中一切皆对象。
1. 基本概念
- 类(class):类就是对某一类事物的一个抽象,用来描述具有相同属性和方法的类型集合。
- 对象(object):对象就是类的一个实例。
- 实例化:由类到对象的一个过程。
- 属性:从属于对象或者类的变量叫做属性。(包括静态属性和动态属性)
- 方法(method):对象可以通过类中的函数来实现相关功能,这个函数叫做类的方法。(方法分为普通方法、类方法和静态方法)
2. 类的定义和实例化
语法格式如下:
class 类名:执行语句…零到多个类变量…零到多个方法…
类中最重要的就是变量和方法,例如我们可以定义如下类:
class Person:name = Nonegender = Noneage = Nonedef set_person_info(self, name, gender, age):self.name = nameself.gender = genderself.age = agedef eat_meal(self):print("{} is eating...".format(self.name))def speak(self):print("{} is speaking...".format(self.name))
上面定义了一个Person
类,它有属性name、gender、age
三个属性以及两个方法。
下面就可以对该类进行实例化了。
p = Person() # 这样就实例化了一个Person
p.set_person_info("Meng", "male", 18) # 调用类中的方法
3. 类中的属性和方法
3.1 属性
3.1.1 类属性
在类命名空间中定义的属性就是类属性,可以直接使用类来进行读取和修改的属性。
class Person:gender = "male" # 定义的类属性print(Person.gender) # 直接通过类来访问类属性可以正常访问
Person.gender = "female" # 直接通过类名来修改类属性,可以修改成功
上面示例中定义的gender
属性为公有类属性,我们还可以定义私有类属性,在变量名前加上双下划线,这样就定义成了私有属性,当然变量的结尾不能也为双下划线,如果前后均为双下划线将仍为公有属性,如下:
class Person:__gender = "male" # 前面加两个下划线,我们就无法直接在类外进行访问print(Person.__gender) # 这样不能成功访问
如果非要访问私有类属性,也不是不可以,可以通过Person._Person__gender
来进行访问。为了防止类中的私有属性被子类或实例化对象修改,Python
内部对其进行了命名修饰。当然如果要设置私有方法,也同样的是在方法前面加上双下划线。
3.1.2 实例属性
声明在方法中,通过self声明的属性,是实例对象所特有的属性。无法通过类来调用实例对象的实例属性。
class Person:def __init__(self):self.name = "Meng" # 实例属性,python中,在调用该函数时,self会自动绑定到实例对象self.age = 18
p = Person() # 此时会调用__init__()方法
print(p.name) # 输出实例属性
p.gender = "male" # 在类外定义实例属性
del p.name # 删除实例属性
print(p.name) # 报错AttributeError: 'Person' object has no attribute 'name'
3.2 方法
实例方法
必须要创建实例才能调用,方法中的第一个参数必须是实例对象,该参数名一般为self
,通过它来传递实例属性和方法(也可以传递类的属性和方法)。
类方法
使用装饰器@classmethod
。方法中第一个参数必须为当前类对象,该参数名一般约定为cls
,通过它来传递类的属性和方法(不能传实例的属性和方法)。实例对象和类对象都可以调用它。
静态方法
使用装饰器@staticmethod
。参数随意,与正常函数相同,但是方法体中不能使用类或实例的任何属性和方法。实例对象和类对象都可以调用它。
import time
class Person:ability = ["eat", "drink", "play", "hahaha"]def __init__(self, name, age, gender):self.name = nameself.age = ageself.gender = genderdef eat(self): # 实例方法print("{} is eating...".format(self.name))@classmethoddef list_ability(cls): # 类方法print("Person can", ", ".join(cls.ability), "and so on.")@staticmethoddef say_time(): # 静态方法print("The time is", time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
p = Person("Meng", 18, "male")
p.eat() # 实例对象调用实例方法
p.list_ability() # 实例对象调用类方法
Person.list_ability() # 类对象调用类方法
p.say_time() # 实例对象调用静态方法
Person.say_time() # 类对象调用静态方法
3.3 类的特殊方法
3.3.1 常用特殊方法
__new__()方法:
该方法是在新式类中新出现的方法,它在构造方法构造实例之前调用,也就是在调用__init__()
方法之前调用,__new__()
可以决定是否调用__init__()
方法。该方法始终都是静态类方法,即使没有加上静态方法装饰器。class Singleton(object):def __new__(cls):# 关键在于这,每一次实例化的时候,我们都只会返回这同一个instance对象if not hasattr(cls, 'instance'):cls.instance = super(Singleton, cls).__new__(cls)return cls.instanceobj1 = Singleton() obj2 = Singleton() obj1.name = "Meng" print(obj2.name) print(id(obj1)) print(id(obj2)) #=====output==== Meng 1480192366856 1480192366856
单例模式:是一种常用的软件设计模式,在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。
__init__()方法:
构造方法,在创建实例时会自动执行,一般用于初始化对象中的各种不参数。__call__()方法:
实例化对象后,在对象后面加上括号会执行该方法。class Person:def __call__(self, *args, **kwargs):print("call Me")person = Person() person()# 这里将会调用__call__()方法
__del__()方法:
析构方法,与__init__()
方法相对应,用于销毁对象,在使用del
删除对象或者代码执行结束时,系统都会自动调用对象中的__del__()
方法。__str__()方法:
可以直接调用该方法将一个对象转换成一个字符串。如果类中重写了该方法,在用print
打印实例或者调用str()
方法时,会输出该方法中返回的内容,而不是调用object.__str__()
方法。在直接打印一个实例对象的时候,会先调用实例对象中重写的__str__()
方法,如果没有则调用实例对象中重写的__repr__()
方法,如果这两个方法都没有重写,则调用object.__str__()
方法(该方法返回一个内存地址)。__repr__()方法:
当程序需要将任何对象与字符串进行连接时,都可先调用__repr__()
方法将对象转换成字符串,然后将两个字符串连接在一起。或者直接使用repr()
函数来将对象转换为字符串。__len__()方法:
当调用len(object)
时会触发,一般是返回一个长度值。__doc__()方法:
打印当前类的描述信息,类下面使用三个引号中包含的内容。__class__()方法:
输出当前实例的类名。__dict__()方法:
输出类中的属性。__getitem__()方法:
返回键对应的值,使用[]
来获取实例属性时会调用。__setitem__()方法:
设置给定键的值,使用[]
设置实例属性时会调用。__delitem__()方法:
删除给定键对应的元素。__contains__()方法:
判断类中是否包含指定元素。__getattribute__()方法:
当程序访问对象的name属性时会被调用__getattr__()方法:
内置使用点号获取实例属性,如s.name
,会先从object
里的__getattribute__
中找,第二步从对象的属性中找,第三步从当前类中找,第四步从父类中找,第五步从__getattr__()
中找,如果没有则直接抛出异常。__setattr__()方法:
使用点号设置类实例属性时会调用。__delattr__()方法:
删除指定属性。
3.3.2 实现迭代器常用特殊方法
__iter__()方法:
该方法返回一个迭代器,迭代器必须包含一个__next__()
方法,该方法返回迭代器的下一个元素。__reversed__()方法:
该方法主要为内建函数reversed()
反转函数提供支持,当程序调用reversed()
函数对指定迭代器执行反转时,是通过该方法实现的。
# 实现斐波那契数列
class Fib:def __init__(self, length):self.first = 0self.second = 1self.__len = lengthdef __next__(self):if self.__len == 0:raise StopIterationself.first, self.second = self.second, self.first + self.secondself.__len -= 1return self.firstdef __iter__(self):return selffib = Fib(10)
for el in fib:print(el, end=" ")
3.3.3 运算符重载的特殊方法
__add__()方法:
加法运算,为”+“运算符提供支持__sub__()方法:
减法运算,为“-”运算符提供支持__mul__()方法:
乘法运算,为“*”运算符提供支持__truediv__()方法:
除法运算,为“/”运算法提供支持__floordiv__()方法:
整除运算,为“//”运算符提供支持__mod__()方法:
求余运算,为“%”运算符提供支持__divmod__()方法:
求余运算,为divmod
运算符提供支持__pow__()方法:
乘方运算,为"**"运算符提供支持__lshift__()方法:
左移运算符,为“<<”运算符提供支持__rshift__()方法:
右移运算符,为“>>”运算符提供支持__and__()方法:
按位与运算,为“&”运算符提供支持__or__()方法:
按位或运算,为“|”运算符提供支持__xor__()方法:
按位异或运算,为”^“运算符提供支持
另外还有一些前面带’r’的重载运算符的方法,用于计算将该对象放在符号后面时的会调用响应的方法。
还有前面带’i’的重载运算符的方法,用于带赋值运算的符号,如+=、*=
等带等号的运算符。
3.3.4 比较运算符重载的方法
__lt__()方法:
为“<”运算符提供支持__le__()方法:
为“<=”运算符提供支持__eq__()方法:
为“==”运算符提供支持__ne__()方法:
为“!=”运算符提供支持__gt__()方法:
为“>”运算符提供支持__ge__()方法:
为“>=”运算符提供支持
3.3.5 与单目运算符相关的特殊方法
__neg__()方法:
为单目求负运算符提供支持__pos__()方法:
为单目求正运算符提供支持__invert__()方法:
为单目取反运算符提供支持。
3.3.6 与类型转换相关的特殊方法
__bytes__()方法:
对应于调用内置函数bytes()
将该对象转换成字节内容,该方法返回bytes
对象。__complex__()方法:
对应于调用内置的complex()
函数将该对象转换成复数形式,该方法返回一个complex
对象。__float__()方法:
对应于调用内置的float()
函数将对象转换成浮点数,该方法返回float
对象。__int__()方法:
对应于调用内置的int()
函数将对象转换为整数,该方法返回一个int
对象。__str__()方法:
对应于调用内置的str()
函数将该对象转换成一个字符串。
3.3.7 与常见内建函数相关的特殊方法
__format__()方法:
对应于调用内置的format()
函数将对象转换成格式化字符串。__hash__()方法:
对应于调用内置的hash()
函数来获取该对象的hash值。__abs__()方法:
对应于调用内置的abs()
函数返回绝对值。__round__()方法:
对应于调用内置的round()
函数执行四舍五入整数。__trunc__()方法:
对应于调用内置的trunc()
函数执行截断取整。使用int()
函数将对象转为整数的时候,如果没有定义__int__()
方法,而是提供了__trunc__()
方法,底层将由__trunc__()
方法提供支持。__floor__()方法:
对应于调用内置的floor()
函数执行向下取整。__ceil__()方法:
对应于调用内置的ceil()
函数,执行向上取整。
4. 类的特性
4.1 封装
封装(Encapsulation)指的是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象的内部信息,而是通过该类中所提供的方法来实现对内部信息的操作和访问。
这也就是前面说过的私有属性和私有方法,是使用前置双下划线完成对属性和方法的私有化,也就是封装。可以通过提供接口来实现对私有属性或私有方法的访问。
4.2 继承
继承是一种创建新类的方式,在python中,新建类可以继承一个或者多个父类, 父类又可以称为基类或者超类,新建的类称为派生类或者子类。
继承分为单继承和多继承
4.2.1 单继承
class Person:def __init__(self, name, age):self.name = nameself.age = agedef eat(self):print("{} is eating".format(self.name))def run(self):print("{} is running".format(self.name))class Student(Person): # 继承Person类def __init__(self, name, age, student_no):super(Student, self).__init__(name, age)self.sno = student_nodef take_exam(self):print("{}(sno:{}) is taking exam".format(self.name, self.sno))student = Student("Meng", 14, 20201234)
student.eat()
student.take_exam()
print(Student.__bases__)# 打印Student的父类
4.2.2 多继承
class Person:def __init__(self, name, age):self.name = nameself.age = agedef eat(self):print("{} is eating".format(self.name))def run(self):print("{} is running".format(self.name))class YoungPioneer:def wear_red_scarf(self):print("A student should wear red scarf.")class Pupil(Person, YoungPioneer): # 继承Person, YoungPioneerdef __init__(self, name, age, student_no):super(Pupil, self).__init__(name, age)self.sno = student_nodef take_exam(self):print("{}(sno:{}) is taking exam".format(self.name, self.sno))student = Pupil("Meng", 10, 20201234)
student.eat()
student.take_exam()
student.wear_red_scarf()
print(Pupil.__bases__)
继承顺序,在python3
中均按照广度优先搜索。
class A:passclass B(A):passclass C(A):passclass D(B, C):pass
print(D.mro())# 打印继承顺序
#=====output======
[<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]
4.3 多态
多态指的是不同的对象调用相同的代码,产生不同的效果,提高代码的灵活性
class Animal:def move(self):raise NotImplementedError("子类中没有实现该方法!")class Dog(Animal):def move(self):print("狗在狂奔!")class Bird(Animal):def move(self):print("鸟在飞翔!")dog = Dog()
bird = Bird()
dog.move()
bird.move()# 同一类型的对象调用同一个方法,表现出不同的行为,这就是多态
这样的话Animal
类就相当于一个抽象类,继承该类的对象需要实现其中没有实现的方法,也可以重写抽象类中已经实现的方法。
抽象类的另一种定义方式如下:
from abc import ABCMeta
from abc import abstractmethodclass Animal(metaclass=ABCMeta):@abstractmethoddef move(self):passclass Dog(Animal):def move(self):print("狗在狂奔!")
使用多态的优点:
- 增加代码的灵活度。
- 以继承和重写父类的方法为前提。
- 调用方法,不会影响到类的内部设计。
Python基础(7)——类和对象(一)相关推荐
- 刻意练习:Python基础 -- Task10. 类与对象
背景 我们准备利用17天时间,将 "Python基础的刻意练习" 分为如下任务: Task01:变量.运算符与数据类型(1day) Task02:条件与循环(1day) Task0 ...
- Python基础78 - 类和对象魔法方法
Python的类和对象 类比介绍 要搞懂类和对象,可以以类比到实际生活经验帮助自身充分了解,例如建房子. 类(class):相当于施工图纸(blueprint) 对象(object):房子(已建成的) ...
- Python基础 定义类和对象(类和对象2)
定义简单的类 面向对象是更大的封装,在一个类中封装多个方法,这样通过这个类创建出来的对象,就可以直接调用这些方法了! 定义只包含方法的类 在python中,要定义一个只包含方法的类,语法格式如下: # ...
- Python之面向对象类和对象
Python之面向对象类和对象 定义一个类:class 定义类的语法: class Test(object):"""类里定义一类事物共同的技能.可以是变量,也可是函数.& ...
- 二十六. Python基础(26)--类的内置特殊属性和方法
二十六. Python基础(26)--类的内置特殊属性和方法 ● 知识框架 ● 类的内置方法/魔法方法案例1: 单例设计模式 # 类的魔法方法 # 案例1: 单例设计模式 class Teacher: ...
- 自动化测试之python基础什么是面对对象之类和对象
前言 学习自动化测试需要掌握一门开发语言,Java.python这两个可以选一个,这里呢笔者推荐的是python语言,因为它比较好学,那么今天呢,笔者就来给大家介绍一下python基础中的面对对象之类 ...
- Python基础之day08-面向对象基础3
Python基础之day08-面向对象基础3 文章目录 Python基础之day08-面向对象基础3 一. 二.类方法 三.静态方法 四.总结实例.类.静态方法 代码仓库地址: https://git ...
- Python基础之day06-面向对象基础1
Python基础之day06-面向对象基础1 文章目录 Python基础之day06-面向对象基础1 一.面向对象介绍 二.定义类及创建类对象 三.在类中通过self获取对象属性 四.__init__ ...
- Python基础之day07-面向对象基础2
Python基础之day07-面向对象基础2 文章目录 Python基础之day07-面向对象基础2 一.继承 二.子类调用父类的方法 三.多层继承与多继承 四.多态 五.封装 代码仓库地址: htt ...
最新文章
- Shell脚本头定义
- 又一无人机新法案将出炉,这次比FAA规定还严
- Android发展Singleton模式
- c++加载python模块,但是PyImport_ImportModule老返回NULL
- vscode 最好的ui主题
- Struts2中指定的校验文件不起作用的原因
- 三种方式使得iOS应用能够在后台进行数据更新和下载
- java源码文件丢恢复需要多少钱,上岸蚂蚁金服!
- react学习(65)--ant design加载中
- 转载 Socket与TCP/IP的关系 转(非常好的一篇文章!)
- 【系统】CentOS、Ubuntu、Debian三个linux比较异同
- 概率论 方差公式_概率论与数理统计课程教学、学习基本要求和教学建议
- MS SQL Server 事务回滚处理!
- 服务器互相备份不同步_94爱分享拍了拍你,这款好用的数据同步备份软件千万不要错过!...
- 被称为最好最易理解的MATLAB入门教程
- ENVI的下载和安装
- 怎么批量查询银行卡号是哪个银行?
- 攻防世界web新手题解题writeup
- The Annotated Transformer(解读Transformer)
- HTML入门笔记(带源文件)
热门文章
- Matlab 2017b遇到绘图低级错误
- 丁卓雅计算机学院,卓雅
- Unity实现:23种设计模式、《游戏编程模式》
- 华清远见-重庆中心-JavaWeb阶段知识点整理
- 魔域mysql修改_魔域数据库修改方案.doc
- clickhouse连接问题解决:Code: 210. DB::NetException: I/O error: Broken pipe, while writing to socket
- ERROR: Could not install packages due to an OSError: [Errno 13] Permission denied问题解决
- Delphi 通过Access Violation地址错误找到错误的哪行代码
- 微信小程序自定义navigationBar顶部导航栏,兼容安卓ios
- 一个资源 C2C 的资源平台