面向对象相关知识简介

  • 类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
  • 类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
  • 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据。
  • 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
  • 实例变量:定义在方法中的变量,只作用于当前实例的类。
  • 继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
  • 实例化:创建一个类的实例,类的具体对象。
  • 方法:类中定义的函数。
  • 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

编程范式

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

  两种最重要的编程范式分别是:面向过程编程和面向对象编程。

1.面向过程编程(Procedural Programming)

  就是程序从上到下一步步执行,一步步从上到下,从头到尾的解决问题。基本设计思路就是程序一开始是要着手解决一个大的问题,然后把一个大问题分解成很多个小问题或子过程,这些子过程再执行的过程再继续分解直到小问题足够简单到可以在一个小步骤范围内解决。

  这样做的问题也是显而易见的,就是如果你要对程序进行修改,对你修改的那部分有依赖的各个部分你都也要跟着修改,举个例子,如果程序开头你设置了一个变量值为1,但如果其它子过程依赖这个值为1的变量才能正常运行,那如果你改了这个变量,那这个子过程你也要修改,假如又有一个其它子程序依赖这个子过程,那就会发生一连串的影响,随着程序越来越大,这种编程方式的维护难度会越来越高。   

  所以我们一般认为,如果你只是写一些简单的脚本,去做一些一次性任务,用面向过程的方式是极好的;但如果你要处理的任务是复杂的,且需要不断迭代和维护的,那还是用面向对象最方便了。

2. 面向对象编程(Object Oriented Programming)

  面向对象编程是一种编程方式,此编程方式的落地需要使用"类"和"对象"来实现,所以,面向对象编程其实就是对"类"和"对象"的使用。

  使用面向对象编程的原因一方面是因为它可以使程序的维护和扩展变得更简单,并且可以大大提高程序开发效率;另外,基于面向对象的程序可以使它人更加容易理解你的代码逻辑,从而使团队开发变得更从容。

2.1 类和对象

  类就是一个模板,模板里可以包含多个函数,函数里实现一些功能;---函数在类中被称为方法

  对象则是根据模板创建的实例,通过实例对象可以执行类中的函数;

  类对象支持两种操作:属性引用和实例化。属性引用使用和Python中所有的属性引用一样的标准语法:obj.name。类对象创建后,类命名空间中所有

的命名都是有效属性名。所以如果类定义是这样:

1
2
3
4
5
6
7
8
#定义一个类,class是定义类的语法;user是类名;(object)是新式类的写法,必须这么写;(额。。什么是新式类?暂时忘记他吧!)
class user(object):
    def __init__(self,name):#初始化函数,(self,name)里是要初始化的属性,其中self为特殊参数,必填项;name为实际参数
        self.name = name#实例变量,作用域就是实例本身
    def uname(self):#---类中创建了一个方法uname
        print("%s is the best!" % self.name)
= user('dd')#---根据类user创建对象i
i.uname()#执行uname方法

2.1.1 零散知识点集锦:

  • 类变量和实例变量

类变量:

是可在类的所有实例之间共享的值(也就是说,它们不是单独分配给每个实例的)。

实例变量:

实例化之后,每个实例单独拥有的变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Test(object): 
    num_of_instance = 0 
    def __init__(self, name): 
        self.name = name 
        Test.num_of_instance += 1 
   
if __name__ == '__main__'
    print Test.num_of_instance 
    t1 = Test('cc'
    print Test.num_of_instance 
    t2 = Test('lucy'
    print t1.name , t1.num_of_instance 
    print t2.name , t2.num_of_instance  
 
-------------------------------打印输出-------------------------------
0
1
cc 2
lucy 2
  • 析构函数

上面我们已经知道构造函数__init__,具有初始化的作用,也就是当该类被实例化的时候就会执行该函数,那么我们就可以把要先初始化的属性放到这个函数里面。

那么与之对应的就是析构函数__del__,用于释放对象占用的资源的函数,做收尾工作,例如关闭数据库、打开临时文件等;

__del__()也是可选的,如果不提供,则Python 会在后台提供默认析构函数

如果要显式的调用析构函数,可以使用del关键字,方式如下:

del对象名

  • 私有属性和方法

1)类的私有属性

__private_attrs:两个下划线开头,声明该属性为私有,不能在类地外部被使用或直接访问。在类内部的方法中使用时self.__private_attrs

2)类的私有方法

__private_method:两个下划线开头,声明该方法为私有方法,不能在类地外部调用。在类的内部调用 slef.__private_methods

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class JustCounter:
    __secretCount = 0  # 私有变量
    publicCount = 0    # 公开变量
  
    def count(self):
        self.__secretCount += 1
        self.publicCount += 1
        print(self.__secretCount)
    def __count(self):#私有方法
        self.__secretCount -=1
        self.publicCount -= 1
        print(self.__secretCount)
counter = JustCounter()
counter.count()
print(counter.publicCount)
print(counter.__secretCount)  # 报错,实例不能访问私有变量
#-----------打印输出----------------
#AttributeError: 'JustCounter' object has no attribute '__secretCount'
 
#---------------------------我是华丽的分割线-------------------------
 
#我们注释掉print(counter.__secretCount),加上下面这句再试试
counter.__count()#访问私有方法
#-----------打印输出----------------
#1
#1
#Traceback (most recent call last):
#File "E:/python/new/new.py", line 20, in <module>
#   counter.__count()#访问私有方法
#AttributeError: 'JustCounter' object has no attribute '__count'

2.2 面向对象的三大特性

2.2.1 封装

封装,顾名思义就是将内容封装到某个地方,以后再去调用被封装在某处的内容。

所以,在使用面向对象的封装特性时,需要:

  • 将内容封装到某处
  • 从某处调用被封装的内容

第一步:将内容封装到某处

self是一个形式参数,当执行obj1=Foo('cc',18)时,self等于obj1;当执行obj2=Foo('coco',22)时,self等于obj2;

所以,内容其实被封装到了对象obj1和obj2中,每个对象中都有name和age属性,在内存里类似于下图来保存。

第二步:从某处调用被封装的内容

调用被封装的内容时,有两种情况:

  • 通过对象直接调用
  • 通过self间接调用

1、通过对象直接调用被封装的内容

上图展示了对象 obj1 和 obj2 在内存中保存的方式,根据保存格式可以如此调用被封装的内容:对象.属性名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Foo:
    def __init__(self, name, age):
        self.name = name
        self.age = age
obj1 = Foo('cc'18)
print(obj1.name)   # 直接调用obj1对象的name属性
print(obj1.age)     # 直接调用obj1对象的age属性
obj2 = Foo('coco'22)
print(obj2.name)    # 直接调用obj2对象的name属性
print(obj2.age)     # 直接调用obj2对象的age属性
----------------------------打印输出-------------------------------------
cc
18
coco
22

2、通过self间接调用被封装的内容

执行类中的方法时,需要通过self间接调用被封装的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 创建一个类,类名是Class_basis
class Class_basis:
    # 在类里面创建了一个方法ret
    def ret(self,):
        # 输出self的内存地址
        print("方法ret的self内存地址"id(self))
 
# 创建一个对象obj,类名后面加括号
obj = Class_basis()
 
# 输出对象obj的内存地址
print("obj对象内存地址"id(obj))
 
# 通过对象调用类中的ret方法
obj.ret()
-------------------打印输出---------------------------
obj对象内存地址 2513776
方法ret的self内存地址 2513776

通过上面的测试可以很清楚的看到obj对象和类的方法中self内存地址是一样的,那么方法中的self就等于obj;

----------self是形式参数,由python自行传递

综上所述,对于面向对象的封装来说,其实就是使用构造方法将内容封装到对象中,然后通过对象直接或者self间接获取被封装的内容。综上所述,对于面向对象的封装来说,其实就是使用构造方法将内容封装到对象中,然后通过对象直接或者self间接获取被封装的内容。

2.2.2 继承

2.2.1 

2.2.3 多态

多态是允许将父对象设置成为和一个或多个它的子对象相等的技术,比如Parent:=Child; 多态性使得能够利用同一类(基类)类型的指针来引用不同类的对象,以及根据所引用对象的不同,以不同的方式执行相同的操作.

python是一种动态语言,参数在传入之前是无法确定参数类型的,so python本身是不支持多态的,不过可以间接实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Animal:
    def __init__(self, name):   
        self.name = name
    def talk(self):            
        raise NotImplementedError("Subclass must implement abstract method")
  
class Cat(Animal):
    def talk(self):
        return 'Meow!'
  
class Dog(Animal):
    def talk(self):
        return 'Woof! Woof!'
  
animals = [Cat('Missy'),
           Dog('Lassie')]
  
for animal in animals:
    print(animal.name + ': ' + animal.talk())
 
-----------------打印输出----------------------
Missy: Meow!
Lassie: Woof! Woof!<span style="font-family: 宋体; font-size: 16px;"> </span>

一鼓作气 博客--第七篇 note7的更多相关文章

  1. 一鼓作气 博客--第八篇 note8

    0.,222] list[33] except IndexError as e : print('index error ') except ValueError as e : print('valu ...

  2. 一鼓作气 博客--第六篇 note6

    1.无论公司付给你多少,你的青春都是廉价的!! 2.通往财富自由之路 --得到APP 3.time 3.1 time.time() t = time.time() print(t) #--->1 ...

  3. 一鼓作气 博客--第五篇 note5

    一.迭代器 二.装饰器 三.生成器 1.生成列表的方式有几种 2.把列表每个数都加1 2.1 data =[1,2,3] for i in map(lambda x:x+1,data):print(i ...

  4. 一鼓作气 博客--第四篇 note4

    1.元祖允许重复数据.只读元组,列表,元祖没有增删改查,比如身份证列表,不允许修改,就存成 元祖. 2. 字典 key-value对 特性: 无顺序 去重 查询速度快,比列表快多了 比list占用内存 ...

  5. 一鼓作气 博客--第三篇 note3

    1 推荐读书消费者行为学 -商业的本质,APP得到,5分钟商学院 2定义字典 dic={'name':haibao,'age':18} 3字典的基本操作--查询 dic={'name':'haibao ...

  6. Scrum 冲刺博客第七篇

    一.当天站立式会议照片一张 二.每个人的工作 (有work item 的ID),并将其记录在码云项目管理中 昨天已完成的工作 对排行榜的界面和功能进行初步设计 今天计划完成的工作 重新对界面进行美化 ...

  7. [转]有哪些值得关注的技术博客(Java篇)

    有哪些值得关注的技术博客(Java篇)   大部分程序员在自学的道路上不知道走了多少坑,这个视频那个网站搞得自己晕头转向.对我个人来说我平常在学习的过程中喜欢看一些教程式的博客.这些博客的特点: 1. ...

  8. # Do—Now——团队冲刺博客_总结篇

    Do-Now--团队冲刺博客_总结篇 目录 博客链接 作者 1. 第一篇(领航篇) @仇夏 2. 第二篇 @侯泽洋 3. 第三篇 @仇夏 4. 第四篇 @周亚杰 5. 第五篇 @唐才铭 6. 第六篇 ...

  9. Django 系列博客(七)

    Django 系列博客(七) 前言 本篇博客介绍 Django 中的视图层中的相关参数,HttpRequest 对象.HttpResponse 对象.JsonResponse,以及视图层的两种响应方式 ...

随机推荐

  1. window.print() 打印页面部分内容的方法

    用 JavaScript 实现页面数据的打印 : 主要是用到了一个 print() 函数 , 该函数将会打印整个 web 页面 body 内的所有 html 数据 ! 使用方法为 window.pri ...

  2. ubantu php7.0版本降级到php5.6

    http://askubuntu.com/questions/756879/cant-install-php5-on-ubuntu-16-04

  3. SQL语法和运算符(一)

    一个数据库通常包含一个或多个表.每个表由一个名字标识,表包含带有数据的记录(行). 一些最重要的SQL命令(SQL对大小写不敏感): 一.SQL语法 select:从数据库中提取数据 update:更 ...

  4. 使用Docker搭建Java Web运行环境

    这周末体验了一下挺火的Docker技术,记录学习笔记. >Docker是干什么的 Docker 是一个基于Linux容器(LXC-linux container)的高级容器引擎,基于go语言开发 ...

  5. Python 爬取网站资源文件

    爬虫原理: 以下来自知乎解释 首先你要明白爬虫怎样工作.想象你是一只蜘蛛,现在你被放到了互联“网”上.那么,你需要把所有的网页都看一遍.怎么办呢?没问题呀,你就随便从某个地方开始,比如说人民日报的首页 ...

  6. 用python DIY一个图片转pdf工具并打包成exe

    最近因为想要看漫画,无奈下载的漫画是jpg的格式,网上的转换器还没一个好用的,于是乎就打算用python自己DIY一下: 这里主要用了reportlab.开始打算随便写几行,结果为若干坑纠结了挺久,于 ...

  7. C# DM5 32位加密

    using System.Security.Cryptography;using System.Text; public static string StringToMD5Hash(string in ...

  8. 18.tty驱动程序框架

    tty驱动程序框架 一.TTY概念解析 在Linux系统中,终端是一类字符型设备,它包括多种类型,通常使用tty来简称各种类型的终端设备. 1.1串口终端(/dev/ttyS*) 串口终端是使用计算机 ...

  9. 【学习篇:他山之石,把玉攻】JavaScript Date() 对象 及 格式化

    Date 对象用于处理日期和时间.  创建 Date 对象的语法: var myDate=new Date() Date 对象会自动把当前日期和时间保存为其初始值. 参数形式有以下5种:   new ...

  10. 在Asp.Net MVC 中配置 Serilog

    Serilog 是一种非常简便记录log 的处理方式,使用Serilog可以生成本地的text文件, 也可以通过 Seq 来在Web界面中查看具体的log内容. 接下来就简单的介绍一下在Asp.Net ...