Python学习笔记第六周

一、基础概念

 面向对象编程

OOP编程是利用“类”和“对象”来创建各种模型来实现对真实世界的描述,使用面向对象编程的原因一方面是因为它可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率 ,另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。

面向对象的几个核心特性如下

Class 类
一个类即是对一类拥有相同属性的对象的抽象、蓝图、原型。在类中定义了这些对象的都具备的属性(variables(data))、共同的方法

Object 对象 
一个对象即是一个类的实例化后实例,一个类必须经过实例化后方可在程序中调用,一个类可以实例化多个对象,每个对象亦可以有不同的属性,就像人类是指所有人,每个人是指具体的对象,人与人之前有共性,亦有不同

Encapsulation 封装
在类中对数据的赋值、内部调用对外部用户是透明的,这使类变成了一个胶囊或容器,里面包含着类的数据和方法

Inheritance 继承
一个类可以派生出子类,在这个父类里定义的属性、方法自动被子类继承

Polymorphism 多态
多态是面向对象的重要特性,简单点说:“一个接口,多种实现”,指一个基类中派生出了不同的子类,且每个子类在继承了同样的方法名的同时又对父类的方法做了不同的实现,这就是同一种事物表现出的多种形态。
编程其实就是一个将具体世界进行抽象化的过程,多态就是抽象化的一种体现,把一系列具体事物的共同点抽象出来, 再通过这个抽象的事物, 与不同的具体事物进行对话。
对不同类的对象发出相同的消息将会有不同的行为。比如,你的老板让所有员工在九点钟开始工作, 他只要在九点钟的时候说:“开始工作”即可,而不需要对销售人员说:“开始销售工作”,对技术人员说:“开始技术工作”, 因为“员工”是一个抽象的事物, 只要是员工就可以开始工作,他知道这一点就行了。至于每个员工,当然会各司其职,做各自的工作。
多态允许将子类的对象当作父类的对象使用,某父类型的引用指向其子类型的对象,调用的方法是该子类型的方法。这里引用和调用方法的代码编译前就已经决定了,而引用所指向的对象可以在运行期间动态绑定

  1、通过例子说明类的用法与类的封装:

  例子:创建一个角色扮演游戏,通过实例化引入不同角色

class Role(object):#新式类,所有的主类,都需要继承object类,object类是一个通类
    n = 123
    def __init__(self,name,role,weapon,life_vaule=100,money=15000):#life_value和money目前为默认参数,不需要实例化时传参
        ‘‘‘
        构造函数:在实例化时做类的初始化工作,将实例化这些定义好的变量名
        ‘‘‘
        self.name = name #如果为普通函数,局部变量在函数结束后会失去意义,但是类中构造函数会将实例化变量一直传递整个类中
        self.role = role
        self.weapon = weapon
        ‘‘‘
        Role类通过该构造函数定义实例化变量名
        ‘‘‘

    def shot(self):  #除了构造函数外,这些函数叫做类的方法
        print(‘shotting....‘)

    def got_shot(self):
        print(‘ah...,I got shot...‘)

    def buy_gun(self,gun_name):#在构造函数以外,也可以通过在函数内定义变量,只是这些变量需要调用时单独复制
        print(‘%s just bought %s‘ %(self.name,gun_name))

print(Role)  #在没有实例化之前,类就已经存在与内存中
#输出
<class ‘__main__.Role‘>

print(Role.n) #Role.n中的n叫做类变量,和类一样,类变量在实例化之前就存在于内存中,同时,实例化后类变量也仍然只存在于类所在内存中,不会复制到实例化的内存中
#输出
123

r1 = Role(‘alex‘,‘police‘,‘B21‘ ) #对Role类进行实例化,实例化过程是将通过构造函数将类中的变量复制为实例化变量,这时通过调用Role中的self,将实例化r1本身也赋值,得到实例化变量
#同时需要注意的是,类的方法,也就是类中的函数仍然保存在类中,不会被复制到实例化变量中,实例化在调用时,通过类方法中的self代表不同实例化的引用,避免类没法区分,这样做的优点为节省内存空间

r2 = Role(‘jack‘,‘terrist‘,‘AK47‘) #对该Role类进行另一个实例化引用

print(r1.name,r1.role,r1.weapon)
#输出alex police B21
print(r2.name,r2.role,r2.weapon)
#输出
jack terrist AK47

  类变量与实例属性(实例变量)

  类的变量查找顺序为当实例变量与类变量重名时,会复制一份实例化变量进行复制,这时的输出覆盖类变量结果,因为实例化变量在自己所在内存空间引入了一个新的实例化变量,而另外一个实例化不受此影响

class Role(object):
    n = 123
    def __init__(self,name,role,weapon,life_vaule=100,money=15000):
        self.name = name
        self.role = role
        self.weapon = weapon

    def shot(self):
        print(‘shotting....‘)

    def got_shot(self):
        print(‘ah...,I got shot...‘)

    def buy_gun(self,gun_name):
        print(‘%s just bought %s‘ %(self.name,gun_name))

print(Role.n)
#输出
123
r1 = Role(‘alex‘,‘police‘,‘B21‘ )
print(r1.n) #类变量属于共有的变量,不会因为实例化而改变
#输出
123
r1.n = 456   #类的变量查找顺序为当实例变量与类变量重名时,会复制一份实例化变量进行复制,这时的输出覆盖类变量结果,因为实例化变量在自己所在内存空间引入了一个新的实例化变量,而另外一个实例化不受此影响
print(r1.n)
#输出
456
r2 = Role(‘jack‘,‘terrist‘,‘AK47‘)
print(r2.n)
#输出
123

  

  类变量的用途:

  大家共用的属性,节省内存开销

class Person(object):

    cn = ‘中国‘
    def __init__(self,name,age,addr):
        self.name = name
        self.age = age
        self.addr = addr

p1 = Person(‘alex‘,22,‘beijing‘)
print(p1.cn)
#输出
#中国
p2 = Person(‘jack‘,22,‘shanghai‘)
print(p2.cn)
#输出
#中国

  当类变量为列表、字典时,可以通过实例化赋值,而将实例化的赋值引入类变量中

class Role(object):
    n = 123
    n_list = []
    def __init__(self,name,role,weapon,life_vaule=100,money=15000):
        self.name = name
        self.role = role
        self.weapon = weapon

    def shot(self):
        print(‘shotting....‘)

    def got_shot(self):
        print(‘ah...,I got shot...‘)

    def buy_gun(self,gun_name):
        print(‘%s just bought %s‘ %(self.name,gun_name))

print(Role.n_list)
#输出
[]
r1 = Role(‘alex‘,‘police‘,‘B21‘ )
print(r1.n_list)
#输出
[]
r1.n_list.append(456) #当类变量为列表或字典时,会因为实例变量添加内容到源类变量中而导致引用改变,但是这也说明了类变量不会随着实例化而被引入到实例化变量中
print(r1.n_list)
#输出
[456]
r2 = Role(‘jack‘,‘terrist‘,‘AK47‘)
print(r2.n_list)
#输出
[456]

  实例化属性的重新增删改

class Role(object):
    n = 123
    n_list = []
    def __init__(self,name,role,weapon,life_vaule=100,money=15000):
        self.name = name
        self.role = role
        self.weapon = weapon

    def shot(self):
        print(‘shotting....‘)

    def got_shot(self):
        print(‘ah...,I got shot...‘)

    def buy_gun(self,gun_name):
        print(‘%s just bought %s‘ %(self.name,gun_name))

r1 = Role(‘alex‘,‘police‘,‘B21‘ )

r1.sex = ‘M‘   #增加实例化属性
print(r1.sex)
#输出M
r1.name = ‘Tom‘  #修改实例化属性
print(r1.name)

print(r1.role)
#输出
police
del r1.role
print(r1.role)#输出
AttributeError: ‘Role‘ object has no attribute ‘role‘

r2 = Role(‘jack‘,‘terrist‘,‘AK47‘)  #对应实例r1的任何操作对r2都没有任何印象
print(r2.sex)
#输出print(r2.sex)AttributeError: ‘Role‘ object has no attribute ‘sex‘

  

  私有属性与私有方法

  a)私有属性(私有变量)

class Role(object):
    n = 123
    def __init__(self,name,role,weapon,life_vaule=100,money=15000):
        self.name = name
        self.role = role
        self.weapon = weapon
        self.__life_vaule = life_vaule  #定义私有变量

    def shot(self):
        print(‘shotting....‘)

    def got_shot(self):
        print(‘ah...,I got shot...‘)

    def buy_gun(self,gun_name):
        print(‘%s just bought %s‘ %(self.name,gun_name))

r1 = Role(‘alex‘,‘police‘,‘B21‘ )

r2 = Role(‘jack‘,‘terrist‘,‘AK47‘)
print(r1.__life_value)
#输出
AttributeError: ‘Role‘ object has no attribute ‘__life_value‘  #私有变量在实例化时没法调用

  对于私有属性,可以通过在类中定义类的方法的方式间接查看私有属性(私有变量)

class Role(object):
    n = 123
    def __init__(self,name,role,weapon,life_vaule=100,money=15000):
        self.name = name
        self.role = role
        self.weapon = weapon
        self.__life_vaule = life_vaule

    def shot(self):
        print(‘shotting....‘)

    def got_shot(self):
        print(‘ah...,I got shot...‘)

    def buy_gun(self,gun_name):
        print(‘%s just bought %s‘ %(self.name,gun_name))

    def show_status(self): #
        print(‘%s has %s life value‘ %(self.name, self.__life_vaule)) #通过类的方法间接查看私有属性

r1 = Role(‘alex‘,‘police‘,‘B21‘ )
r1.show_status() #调用该类方法
#输出alex has 100 life value
r2 = Role(‘jack‘,‘terrist‘,‘AK47‘)

  b)私有方法

  同私有属性一样,前面加def  __show_status(self):  就将方法变为私有方法了

class Role(object):
    n = 123
    def __init__(self,name,role,weapon,life_vaule=100,money=15000):
        self.name = name
        self.role = role
        self.weapon = weapon
        self.__life_vaule = life_vaule

    def shot(self):
        print(‘shotting....‘)

    def got_shot(self):
        print(‘ah...,I got shot...‘)

    def buy_gun(self,gun_name):
        print(‘%s just bought %s‘ %(self.name,gun_name))

    def show_status(self):
        print(‘%s has %s life value‘ %(self.name, self.__life_vaule)) #通过类的方法间接查看私有变量

    def __show_status(self):  #定义私有方法
        print(‘aa‘)

r1 = Role(‘alex‘,‘police‘,‘B21‘ )
r1.show_status() #调用该类方法
#输出
#alex has 100 life value
r2 = Role(‘jack‘,‘terrist‘,‘AK47‘)
r1.__show_status() 

  析构函数:

  不需要加任何变量,在实例化调用结束后,自动执行 ,目的完成实例化的收尾工作,例如断开数据库 关闭打开的文件等

class Role(object):
    n = 123
    def __init__(self,name,role,weapon,life_vaule=100,money=15000):
        self.name = name
        self.role = role
        self.weapon = weapon
        self.__life_vaule = life_vaule

    def shot(self):
        print(‘shotting....‘)

    def got_shot(self):
        print(‘ah...,I got shot...‘)

    def buy_gun(self,gun_name):
        print(‘%s just bought %s‘ %(self.name,gun_name))

    def show_status(self):
        print(‘%s has %s life value‘ %(self.name, self.__life_vaule)) #通过类的方法间接查看私有变量

    def __del__(self): #析构函数,不需要加任何变量,在实例化调用结束后,自动执行 ,目的完成实例化的收尾工作,例如断开数据库 关闭打开的文件等
        print(‘%s is gone‘ % self.name)

r1 = Role(‘alex‘,‘police‘,‘B21‘ )
r1.got_shot()
#输出
ah...,I got shot...
r2 = Role(‘jack‘,‘terrist‘,‘AK47‘)
r2.got_shot()
#输出
ah...,I got shot...
alex is gone    #由于r1在实例化执行完所需任务后没有明确表示实例化引用结束,所以在r2也引用结束后,两者再先后自动执行析构函数
jack is gone

如果需要在r1结束后立即自动执行析构函数,需要使用del 方法

class Role(object):
    n = 123
    def __init__(self,name,role,weapon,life_vaule=100,money=15000):
        self.name = name
        self.role = role
        self.weapon = weapon
        self.__life_vaule = life_vaule

    def shot(self):
        print(‘shotting....‘)

    def got_shot(self):
        print(‘ah...,I got shot...‘)

    def buy_gun(self,gun_name):
        print(‘%s just bought %s‘ %(self.name,gun_name))

    def show_status(self):
        print(‘%s has %s life value‘ %(self.name, self.__life_vaule)) #通过类的方法间接查看私有变量

    def __del__(self): #析构函数,不需要加任何变量,在实例化调用结束后,自动执行 ,目的完成实例化的收尾工作,例如断开数据库 关闭打开的文件等
        print(‘%s is gone‘ % self.name)

r1 = Role(‘alex‘,‘police‘,‘B21‘ )
r1.got_shot()
#输出
ah...,I got shot...
del r1  #在r1执行完毕后立即删除该r1实例化的名字,表示 引用完毕,会立即自动执行析构函数
#输出
alex is gone
r2 = Role(‘jack‘,‘terrist‘,‘AK47‘)
r2.got_shot()

#输出
ah...,I got shot...
jack is gone

 备注:

  python程序释放内存的条件,在python解释器在周期性扫描过程中,只有检测到变量名或者实例化的名称消失后才会释放内存,所以如果类与函数、变量如果名称仍然存在,会一直占据内存不会主动释放,除非通过del删除

 

 

2、上述例子将类的概念与类的封装介绍了一下,下面继续介绍类的继承:

  

时间: 2024-11-12 15:19:04

Python学习笔记第六周的相关文章

Linux学习笔记第六周第四次课(3月15日)

六周第四次课(3月15日) 复习 扩展 打印某行到某行之间的内容http://ask.apelearn.com/question/559 按关键词打印内容,#sed -n '/\[abcd\]/,/\[rty\]/'p test 按行数打印内容,# sed -n '4,8'p test sed转换大小写 http://ask.apelearn.com/question/7758 sed中,使用\u表示大写,\l表示小写 1. 把每个单词的第一个小写字母变大写: sed 's/\b[a-z]/\u

python学习笔记十六 django深入学习一

django 请求流程图 django 路由系统 在django中我们可以通过定义urls,让不同的url路由到不同的处理函数 from . import views urlpatterns = [ url(r'^articles/2003/$', views.special_case_2003), #精确匹配 url(r'^articles/([0-9]{4})/$', views.year_archive), #动态路由 url(r'^articles/([0-9]{4})/([0-9]{2

Python学习笔记(六)之 面向对象

一.面向过程 VS 面向对象 编程范式 编程是程序员用特定的语法+数据结构+算法组成的代码来告诉计算机如何执行任务的过程 ,一个程序是程序员为了得到一个任务结果而编写的一组指令的集合,正所谓条条大路通罗马,实现一个任务的方式有很多种不同的方式,对这些不同的编程方式的特点进行归纳总结得出来的编程方式类别,即为编程范式.不同的编程范式本质上代表对各种类型的任务采取的不同的解决问题的思路,大多数语言只支持一种编程范式,当然也有些语言可以同时支持多种编程范式.两种最重要的编程范式分别是面向过程编程和面向

python学习笔记-(六)深copy&amp;浅copy

在python中,对象赋值实际上是对象的引用.当创建一个对象,然后把它赋给另一个变量的时候,python并没有拷贝这个对象,而只是拷贝了这个对象的引用. 1. 赋值 赋值其实只是传递对象引用,引用对象id是一样的.原始列表改变,被赋值的b也会做相同的改变. 1 2 3 4 5 6 7 8 9 10 11 12 13 >>> alist = [1,2,3,["a","b"]] >>> b = alist >>> p

Python学习笔记(六)多进程实现并发服务器

这个相对于多进程更加简单,每accept一个新的连接就创建一个新的线程.代码如下: # coding: utf-8 import socket import sys import errno import threading from time import ctime class ClientThread(threading.Thread): def __init__(self, client_socket, client_address): threading.Thread.__init__

Python学习笔记(六)

json & pickle 模块(序列化) json和pickle都是序列化内存数据到文件 json和pickle的区别是: json是所有语言通用的,但是只能序列化最基本的数据类型(字符串.字典.列表),像函数.类.python日期都不能序列化 pickle可以序列化python几乎所有的数据类型 如果两个程序都需要交互内存数据,如果都是python语言的情况下,复杂的交互用pickle. 用于序列化的两个模块 json,用于字符串 和 python数据类型间进行转换 pickle,用于pyt

[python]python学习笔记(六)——界面编程

python图像用户编程1,导入模块 import Tkinter或者from Tkinter import *2,创建顶层窗口对象 top=Tkinter.Tk()3,在顶层窗口对象上创建各个功能模块 Tk有两个坐标管理器用来协助将组件放在正确的位置,Packer,另外一个管理器是网格Grid4,将GUI 模块和底层代码相连接5,进入主事件循环 Tkinter.mainloop() helloword程序:#!/usr/bin/python import Tkinter top=Tkinter

Python学习笔记第八周

本节内容: 1.动态导入模块 2.断言机制 3.SocketServer 1.动态导入模块 有时在编程过程中,如果知道模块对应的字符串,可以通过动态导入的方式将该字符对应的模块进行动态导入 导入的方式有两种: 1.python解释器默认的方式导入 2.官方推荐动态导入方式 下面来分别介绍以下两种方式: lib模块中包括aa文件,aa文件内容如下: class C(object): def __init__(self): self.name = 'gavin' 通过方法一导入: modname =

Python学习笔记(六)map/reduce

摘抄:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/0014317852443934a86aa5bb5ea47fbbd5f35282b331335000 本文章完全用来个人学习复习,侵删: map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回. 举例说明,比如我们有一个函数f(x)=x