第九周:对象式编程
1.万物皆对象
对象是一种相对独立的存在,类是描述某一类对象的统称,对象是类的实例
类由属性和方法来描述,对应变量和函数
类 = {属性} + {方法}
如果类是<C>,其派生的对象是<O>,属性是<A>,方法是<B>,那么访问方法结构如下:
属性访问:<O>.<A>
方法访问:<O>.<B>()
对象是类的实例化结果,每次实例化会创建一个对象
Python 语言所有数据类型和语法结构都是类,每个变量都是对象
txt = "Hello,Python!"
txt_upper = txt.upper()
print(txt_upper)
ends_with_python = txt_upper.endswith("PYTHON!")#检查字符串末尾是否包含特定字符串
print(ends_with_python)
'''
HELLO,PYTHON!
True
'''
面向对象程序设计一种编程思想,重点在于建立面向对象的高阶抽象
面向对象程序设计有三大基本特征:封装、继承、多态
对象构造法是一种通过构建对象及对象间交互关系解决问题的计算方法
对象构造法要求对象具备三个特征:独立性、功能性、交互性
对象构造法定义对象在软件系统中的表现和相互作用
2.类的创建
类在创建时需要定义构造函数、属性和方法,在使用时通常需要实例化
Python 语言通过保留字 class 定义一个类
clsaa <类名>:#类名建议采用首字母大写的单词组合
<语句块>
clsaa DemoClass:
pass
class <类名>:
def__int__(self,<参数列表>):#self表示类实例自身,在类内部
<语句块>
<语句块>
#构造函数,固定采用__int__()作为名字,由双下划线开始和结束
#构造函数的作用:当用类生成对象时,接收参数,执行构造函数的内容,完成初始操作,实现一次"实例化"
<对象名> = <类名>([<参数>])
#实例化后的对象,可通过某种方法访问方法和属性
<对象名>.<属性名>
<对象名>.<方法名>
#例如定义一个包含构造函数的DemoClass类、
class DemoClass:
def __init__(self,name):
print(name)
dc1 = DemoClass("小王")
dc2 = DemoClass("小李")
小王
小李
3.属性和方法
Python 类的属性总体包括两种:类属性和实例属性
类属性是所有实例共享,实例属性由实例名独享
class <类名>:
<类属性变量名> = <类属性初值>
def __int__(self,<参数列表>)
self.<实例属性变量名> = <实例属性初值>
class DemoClass:
count = 0
def __init__(self,name,age):
self.name = name
self.age = age
DemoClass.count += 1
dc1 = DemoClass("小王",23)
dc2 = DemoClass("小李",21)
print("总数:",DemoClass.count)
print(dc1.name,dc2.name)
总数: 2
小王 小李
属性根据名称前是否包含两个下划线(__)分为:公开属性和私有属性
防止外部代码直接访问对象内部的状态,对于私有属性,直接在属性名前加上 __,如 __count.
设定为私有属性后,不能通过<对象名>.<实例属性名>或<类名>.<类属性>方式直接访问
class DemoClass:
__count = 0
def __init__(self,name,age):
self.__name = name
self.__age = age
DemoClass.__count += 1
dc1 = DemoClass("小王",23)
dc2 = DemoClass("小李",21)
print("总数:",DemoClass.__count)
print(dc1.__name,dc2.__name)
Traceback (most recent call last):
File "/Users/chuji/Desktop/个人/计算机/Python/课内/ts1.py", line 10, in <module>
print("总数:",DemoClass.__count)
^^^^^^^^^^^^^^^^^
AttributeError: type object 'DemoClass' has no attribute '__count'
Python 类的方法主要有 3 种:类方法、实例方法、保留方法
类方法是所有实例对象可以共享使用的方法;实例方法是实例对象使用的方法,由实例对象独享
class<类名>:
@classmethod#装饰器,标记符
def<方法名>(cls,<参数列表>)#至少包含一个参数,表示类对象
#<类名>.<方法名>(<参数列表>)或<对象名>.<方法名>(<参数列表>)
class DemoClass:
count = 0
def __init__(self,name):
self.name = name
DemoClass.count += 1
@classmethod
def getChrCount(cls):
s = "零一二三四五六七八九十多"
idx = cls.count if cls.count<10 else 10
return s[idx]
dc1 = DemoClass("小王")
dc2 = DemoClass("小李")
print(dc1.getChrCount())
print(DemoClass.getChrCount())
二
二
实例方法格式定义
class<类名>:
def<方法名>(self,<参数列表>)#至少包含一个参数self,用于索引实例属性
#使用:<对象名>.<方法名>(<参数列表>)
class DemoClass:
def __init__(self,name):
self.name = name
def lucky(self):
s = 0
for c in self.name:
s += ord(c)%100
return s
dc1 = DemoClass("小王")
dc2 = DemoClass("小李")
print(dc1.name,"的幸运数字是:",dc1.lucky())
print(dc2.name,"的幸运数字是:",dc2.lucky())
小王 的幸运数字是: 146
小李 的幸运数字是: 113
保留方法
class<类名>:
def <保留方法名>(<参数列表>)
……
class DemoClass:
count = 0
def __init__(self,name):
self.name = name
DemoClass.count += 1
def __len__(self):
return len(self.name)
dc1 = DemoClass("小王")
dc2 = DemoClass("小李")
print(len(dc1))
print(len(dc2))
2
2
4.类的实例化
类的实例化由构造函数和析构函数组成
实例化包括对象创建和对象删除,前者由构造函数负责,后者由析构函数负责
class DemoClass:
def __init__(self,name):
self.name = name
def __del__(self):
print("再见",self.name)
dc1 = DemoClass("小王")
del dcl
print(dcl.name)
Traceback (most recent call last):
File "/Users/chuji/Desktop/个人/计算机/Python/课内/ts1.py", line 9, in <module>
print(dc1.name)
^^^
NameError: name 'dc1' is not defined
再见 小王
5.实例十五:简单图书借阅系统
#LibraryMangeSystem.py
class Book:#Book类的属性包括id,title,suthor,is_borrowed;方法包括borrow,return_book,statue
def __init__(self,idx,title,author):
self.id = idx
self.title = title
self.author = author
self.is_borrowed = False
def borrow(self):
if not self.is_borrowed:
self.is_borrowed = True
return True
else:
return False
def return_book(self):
if self.is_borrowed:
self.is_borrowed = False
return True
else:
return False
def status(self):
return "可借阅" if not self.is_borrowed else "已借阅"
class Library:#属性包括books;方法包括add_book(book),borrow_book(book_id),return_book(book_id),list_books()
def __init__(self):
self.books = {}
def add_book(self,book):
self.books[book.id] = book
def borrow_book(self,book_id):
if book_id in self.books and self.books[book_id].borrow():
print("图书{}借阅成功".format(self.books[book_id].title))
else:
print("图书{}无法借阅".format(self.books[book_id].title))
def return_book(self,book_id):
if book_id in self.books and self.books[book_id].return_book():
print("图书{}归还成功".format(self.books[book_id].title))
else:
print("图书归还出错")
def list_books(self):
for book in self.books.values():
print("ID:{:4},书名{:20},作者:{:15},状态:{:10}".format(book.id,book.title,book.author,book.status()))
library = Library()
library.add_book(Book(1,"The Littel Prince","Antoine"))
library.add_book(Book(2,"1984","George Orwell"))
library.list_books()
library.borrow_book(1)
library.list_books()
library.return_book(1)
library.list_books()
6.类的继承
继承是面向对象程序设计的精髓,是代码复用的高级抽象
继承是能够完全拥有一个类的属性和方法,并可自由扩展的过程
一个子类可以继承多个父亲,称为多继承;Python 最基础的类是 object 类。
扩展:Python 对象的三个要素:标识、类型、值
派生类可以直接使用基类的属性和方法,通常在定义时声明继承关系
class <类名>(<基类名>):
def__init__(self,<参数列表>)
<语句块>
...
class DemoClass:
count = 0
def __init__ (self,name):
self.name = name
DemoClass.count += 1
def getName(self):
return self.name
class HumanNameClass(DemoClass):
def printName(self):
return str(DemoClass.count) + self.name + "同志"
dc1 = HumanNameClass("小王")
print(dc1.getName())
print(dc1.printName())
'''
小王
1小王同志
HumanNameClass继承了DemoClass
'''
与继承关系判断相关的 Python 标准函数(只能基类的公开属性和方法)
函数 | 描述 |
isinstance(obj,cls) | 判断对象 obj 是否是类 cls 的实例或子类实例,返回 True/False |
issubclass(cls1,cls2) | 判断类 cls1 是否是类 cls2 的子类,返回 True/False |
重载(override)是派生类对基类属性或方法的再定义
步骤一:优先使用派生类重定义的属性和方法
步骤二:若步骤一未命中,寻找基类的属性和方法
步骤三:若步骤一和步骤二均未命中,寻找超类的属性和方法
class DemoClass:
count = 0
def __init__(self,name):
self.name = name
DemoClass.count += 1
class HumanNameClass(DemoClass):
count = 99
def __init__(self,name):
self.name = name
HumanNameClass.count -= 1
def printCount(self):
return str(HumanNameClass.count) + self.name
dc1 = HumanNameClass("小王")
print(dc1.printCount())
'''
98小王
'''
7.类的运算
Python 运算符包括算术、比较、逻辑、位、赋值、特殊、函数等运算类别
操作数 运算符 操作数
算术运算符:+ - * / // % **
比较运算符:== != < > <= >=
逻辑运算符:and or not
位运算符:& | ^ ~ << >>
赋值运算符:= += -=
特殊运算符:is is not in not in
函数操作符:一些用于计算的 Python 标准函数
Python 将运算符关联保留函数,自定义类可以重载运算符功能
二元算术运算符的保留方法:
保留方法 | 操作符操作 | 描述 |
.__neg__(self) | -obj | 定义对象取负的操作逻辑 |
.__pos__(self) | +obj | 定义对象取正的操作逻辑 |
.__abs__(self) | abs(obj) | 定义对象绝对值的运算逻辑 |
.__invert__(self) | ~obj | 定义对象取反的操作逻辑 |
.__add__(self,other) | obj + other | 定义两个对象加厚的运算逻辑 |
.__sub__(self,other) | obj - other | 定义两个对象减法的运算逻辑 |
.__mul__(self,other) | obj + other | 定义两个对象乘法的运算逻辑 |
.__truediv__(self,other) | obj / other | 定义两个对象除法的运算逻辑 |
.__floordiv__(self,other) | obj // other | 定义两个对象整数除的运算逻辑 |
.__mod__(self,other) | obj %other | 定义两个对象模的运算逻辑 |
.__divmod__(self,other) | divmod(obj,other) | 定义两个对象除模的运算逻辑 |
.__pow__(self,other) | obj**other | 定义对象幂的运算逻辑 |
.__lshift__(self,other) | obj<<other | 定义对象左移的运算逻辑 |
.__rshift__(self,other) | obj>>other | 定义对象右移的运算逻辑 |
.__and__(self,other) | obj&other | 定义两个对象位与的运算逻辑 |
.__xor__(self,other) | obj^other | 定义两个对象位异或的运算逻辑 |
.__or__(self,other) | obj | other | 定义两个对象位或的运算逻辑 |
class NewList(list):
def __add__(self, other):
result = []
for i in range(len(self)):
try:
result.append(self[i] + other[i])
except:
result.append(self[i])
return result
ls = NewList([1,2,3,4,5,6])
lt = NewList([1,2,3,4])
print(ls+lt)
'''
[2, 4, 6, 8, 5, 6]
'''
比较运算符的保留方法
保留方法 | 操作符操作 | 描述 |
.__It__(self,other) | obj < other | 两个对象的比较操作 |
.__le__(self,other) | obj <= other | |
.__eq__(self,other) | obj == other | |
.__ne__(self,other) | obj != other | |
.__gt__(self,other) | obj > other | |
.__ge__(self,other) | obj >= other |
成员运算符的保留方法
保留方法 | 操作符操作 | 描述 |
.__getitem__(self,key) | obj[k] | 定义获取对象中序号 k 元素的运算逻辑,k 为整数 |
.__setitem__(self,key,v) | obj[k] = v | 定义赋值对象中序号 k 元素的运算逻辑 |
.__delitem__(self,key) | del obj[k] | 定义删除对象中序号 k 元素的运算逻辑 |
.__reversed__(self) | obj.reversed() | 定义对象逆序的运算逻辑 |
.__contains__(self,item) | item in obj | 定义 in 操作符对应的运算逻辑 |
其他常用运算符的保留方法
保留方法 | 操作符操作 | 描述 |
.__int__(self) | int(obj) | 定义对象整数转换的运算逻辑 |
.__float__(self) | float(obj) | 定义对象浮点数转换的运算逻辑 |
.__complex__(self) | complex(obj) | 定义对象复数转换的运算逻辑 |
.__repr__(self) | repr(obj) | 定义对象可打印字符串的运算逻辑 |
.__str__(self) | str(obj) | 定义对象字符串转换操作的运算逻辑 |
.__len__(self) | len(obj) | 定义对象长度操作的运算逻辑 |
.__round__(self) | round(obj) | 定义对象四舍五入的运算逻辑 |
.__bytes__(self) | bytes(obj) | 定义对象字节串转换的运算逻辑 |
.__bool__() | bool(obj) | 定义对象布尔运算的运算逻辑 |
.__format__(self,spec) | obj.format() | 定义对象格式化输出的运算逻辑 |
8.实例十六:图像的四则运算
# ImageOperations.py
import numpy as np
from PIL import Image
#总体定义了ImageObject类
class ImageObject:
def __init__(self, path=""):
self.path = path
try:
self.data = np.array(Image.open(path))
except:
self.data = None
def __add__(self, other):
image = ImageObject()
try:
image.data = np.mod(self.data + other.data, 255)
except:
image.data = self.data
return image
def __sub__(self, other):
image = ImageObject()
try:
image.data = np.mod(self.data - other.data, 255)
except:
image.data = self.data
return image
def __mul__(self, factor):
image = ImageObject()
try:
image.data = np.mod(self.data * factor, 255)
except:
image.data = self.data
return image
def __truediv__(self, factor):
image = ImageObject()
try:
image.data = np.mod(self.data // factor, 255)
except:
image.data = self.data
return image
def saveImage(self, path):
try:
im = Image.fromarray(self.data)
im.save(path)
return True
except:
return False
a = ImageObject("earth.jpg")
b = ImageObject("gray.png")
(a + b).saveImage("result_add.png")
True
(a - b).saveImage("result_sub.png")
True
(a * 2).saveImage("result_mul.png")
True
(a / 2).saveImage("result_div.png")
True
9.模块
模块和程序包是组织和重用代码的重要结构
模块封装:模块是一个命名空间,对应单独的.py 文件
module_var = 1
class module_class:
mc_classattr = 1
def __init__(self,mc_instattr = 1):
self.mc_classattr = mc_instattr
def mc_func(self):
return "Method with a count of {}".format(self.mc_classattr)
def module_func():
print("Module Function")
print("Module Statement")
>>>import m
Module Statement
>>>print(m.module_var)
1
>>>mc = m.module_class(99)
>>>print(mc.mc_func())
Method with a count of 99
10.程序包
程序包通过 __init__.py 文件实现命名空间的组织,本质上属于目录
程序包包含了多重命名空间,import 可以引入任何一级命名空间
import pkg.pkg1
import pkg.pkg2.m1
程序包在组织程序逻辑上十分有用,可将所有有关的类和函数放在一个模版中
game_engine/
| __init__.py
| graphics.py
| audio.py
#当需要时可分别导入这些模块
from game_engine import graphics
from game_engine import audio
标签:__,.__,name,对象,self,编程,other,第九,def
From: https://blog.csdn.net/DA_CK/article/details/143415012