一、面向对象编程

1、简介
  面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想。OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数。
面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行。为了简化程序设计,面向过程把函数继续切分为子函数,即把大块函数通过切割成小块函数来降低系统的复杂度。
  而面向对象的程序设计把计算机程序视为一组对象的集合,而每个对象都可以接收其他对象发过来的消息,并处理这些消息,计算机程序的执行就是一系列消息在各个对象之间传递。
  在Python中,所有数据类型都可以视为对象,当然也可以自定义对象。自定义的对象数据类型就是面向对象中的类(Class)的概念。

2、类的构成
类Class由3部分构成
类的名称:类名
类的属性:一组数据
类的方法:允许对类进行操作的方法(行为)

类里面的变量可以叫做静态属性、静态变量、静态字段
类里面的函数一般叫做方法

3、定义类
定义一个类,格式如下:
class 类名:
  静态属性
  动态方法

4、举例:

class Person:   #定义一个人类
role = 'person' #人的角色属性都是人
def walk(self): #人都可以走路,也就是有一个走路方法
print("person is walking...") print(Person.role) #查看人的role属性
print(Person.walk) #引用人的走路方法,注意,这里不是在调用

5、__init__方法
  由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。通过定义一个特殊的__init__方法,在创建实例的时候,就把name,score等属性绑上去:

class Student:
def __init__(self, name, score):
self.name = name
self.score = score

注意:特殊方法“init”前后有两个下划线!!!
注意到__init__方法的第一个参数永远是self,表示创建的实例本身,因此,在__init__方法内部,就可以把各种属性绑定到self,因为self就指向创建的实例本身。
有了__init__方法,在创建实例的时候,就不能传入空的参数了,必须传入与__init__方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去。

6、实例化对象
类名加括号就是实例化,会自动触发__init__函数的运行,可以用它来为每个实例定制自己的特征

实例化对象的过程:
1)在内存中创建了一个内存空间,存储类
2)在这个类内存空间中创建静态变量和特殊方法__init__的内存地址,和动态方法的内存地址
3)在内存中创建了一个内存空间,存储这个变量

一般情况下:
类中的静态属性通过类名去调用或修改
类中的动态方法通过对象去调用执行

class 类名:
def __init__(self,参数1,参数2):
self.对象的属性1 = 参数1
self.对象的属性2 = 参数2 def 方法名(self):pass
def 方法名2(self):pass

对象名 = 类名(1,2) #对象就是实例,代表一个具体的东西
         #类名() : 类名+括号就是实例化一个类,相当于调用了__init__方法
        #括号里传参数,参数不需要传self,其他与init中的形参一一对应
        #结果返回一个对象
对象名.对象的属性1#查看对象的属性,直接用 对象名.属性名 即可

对象名.方法名() #调用类中的方法,直接用 对象名.方法名() 即可

例子:

class Person:   #定义一个人类
role = 'person' #人的角色属性都是人
def __init__(self,name):
self.name = name # 每一个角色都有自己的昵称; def walk(self): #人都可以走路,也就是有一个走路方法
print("person is walking...") p1 = Person('Mike') #实例化人p1
print(p1.role) #查看人的role属性
print(p1.name) #查看人的name属性
p1.walk() #引用人的走路方法

实例化的过程就是类——>对象的过程

7、self
self:在实例化时自动将对象/实例本身传给__init__的第一个参数,你也可以给他起个别的名字,但是约定俗成都这么写。

8、类属性的补充

8.1、我们定义的类的属性到底存到哪里了?有两种方式查看
dir(类名):查出的是一个名字列表
类名.__dict__:查出的是一个字典,key为属性名,value为属性值

print(dir(Person))
#['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
# '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__',
# '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'role', 'walk'] print(Person.__dict__)
#{'__module__': '__main__', 'role': 'person', '__init__': <function Person.__init__ at 0x0054FA98>,
# 'walk': <function Person.walk at 0x0054FA50>, '__dict__': <attribute '__dict__' of 'Person' objects>,
# '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None}

8.2、特殊的类属性
类名.__name__# 类的名字(字符串)
类名.__doc__# 类的文档字符串
类名.__base__# 类的第一个父类(在讲继承时会讲)
类名.__bases__# 类所有父类构成的元组(在讲继承时会讲)
类名.__dict__# 类的字典属性
类名.__module__# 类定义所在的模块
类名.__class__# 实例对应的类(仅新式类中)

9、类名称空间与对象的名称空间
创建一个类就会创建一个类的名称空间,用来存储类中定义的所有名字,这些名字称为类的属性

而类有两种属性:静态属性和动态属性

静态属性就是直接在类中定义的变量
动态属性就是定义在类中的方法

其中类的数据属性也叫静态属性是共享给所有对象的,通过id可以看出在内存中的地址是一样的

print(id(Person.role))
#
print(id(p1.role))
#

而类的动态属性是绑定到所有对象的,通过引用类的动态方法可以看出方法在内存中的地址是不一样的

print(Person('Tom').walk)
#<bound method Person.walk of <__main__.Person object at 0x01E83050>>
print(p1.walk)
#<bound method Person.walk of <__main__.Person object at 0x01E72F70>>

创建一个对象/实例就会创建一个对象/实例的名称空间,存放对象/实例的名字,称为对象/实例的属性
在obj.name会先从obj自己的名称空间里找name,找不到则去类中找,类也找不到就找父类...最后都找不到就抛出异常

二、面向对象的三大特性:继承,多态,封装

2.1继承

继承是一种创建新类的方式,在python中,新建的类可以继承一个或多个父类,父类又可称为基类或超类,新建的类称为派生类或子类
python中类的继承分为:单继承和多继承

2.2、单继承
比如,我们已经编写了一个名为Animal的class,有一个run()方法可以直接打印:

class Animal:
def run(self):
print('Animal is running...')

当我们需要编写Dog和Cat类时,就可以直接从Animal类继承:

class Dog(Animal):
pass
class Cat(Animal):
pass

对于Dog来说,Animal就是它的父类,对于Animal来说,Dog就是它的子类。Cat和Dog类似。

继承有什么好处?最大的好处是子类获得了父类的全部功能。
由于Animial实现了run()方法,因此,Dog和Cat作为它的子类,什么事也没干,就自动拥有了run()方法:

dog = Dog()
dog.run() cat = Cat()
cat.run() 运行结果如下:
Animal is running...
Animal is running...

继承的第二个好处需要我们对代码做一点改进。你看到了,无论是Dog还是Cat,它们run()的时候,显示的都是Animal is running...,符合逻辑的做法是分别显示Dog is running...和Cat is running...,因此,对Dog和Cat类改进如下:

class Dog(Animal):
def run(self):
print('Dog is running...') class Cat(Animal):
def run(self):
print('Cat is running...') 再次运行,结果如下:
Dog is running...
Cat is running...

在单继承中,如果只想执行父类的属性或方法,那么子类的属性名或方法不能与父类中的属性名或方法名重复,否则只会执行子类中的属性或方法,相当于重写
如果既想执行子类的方法,又想执行父类中的方法,有2种方法:
方法1、使用super

class A:
def func(self):
print('in A') class B(A):
def func(self):
super().func()
print('in B') b1 = B()
b1.func()
结果:
in A
in B

方法2、方法内调用

class A:
def func(self):
print('in A') class B(A):
def func(self):
A.func(self)
print('in B') b1 = B()
b1.func()
结果:
in A
in B

2.3、多继承
继承还可以一级一级地继承下来,就好比从爷爷到爸爸、再到儿子这样的关系。而任何类,最终都可以追溯到根类object,这些继承关系看上去就像一颗倒着的树。比如如下的继承树:

class Base:
def test(self):
print('---Base---') class A(Base):
def test(self):
print('---A---')
def testA(self):
print('---A---') class B(Base):
def test(self):
print('---A---')
def testB(self):
print('---B---') class C(A, B):
pass c = C()
c.test()

类A和类B都继承类Base,类C继承类A和B
调用类C的test方法时,依次查看的顺序是类A,类B,类Base
如果定义类C时写成class C(B, A):,则先查看B,再查看A

print(C.__mro__)  #在Python3中可以查看C类的对象搜索方法时的先后顺序。
(<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.Base'>, <class 'object'>)

2.3、查看继承

>>> SubClass1.__bases__ #__base__只查看从左到右继承的第一个子类,__bases__则是查看所有继承的父类
(<class '__main__.ParentClass1'>,)
>>> SubClass2.__bases__
(<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)

提示:如果没有指定基类,python的类会默认继承object类,object是所有python类的基类,它提供了一些常见方法(如__str__)的实现。

>>> ParentClass1.__bases__
(<class 'object'>,)
>>> ParentClass2.__bases__
(<class 'object'>,)

当子类和父类都存在相同的run()方法时,我们说,子类的run()覆盖了父类的run(),在代码运行的时候,总是会调用子类的run()。这样,我们就获得了继承的另一个好处:多态。

继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写。

2.4、重写
就是子类中,有一个和父类相同名字的方法,在子类中的方法会覆盖掉父类中同名的方法

class Cat:
def sayHello(self):
print("halou...")
class Bosi(Cat):
def sayhello(self):
#调用父类的方法sayHello,在python2和3中都可以用,在参数中需要加self
Cat.sayHello(self)
#调用父类的方法sayHello,在python3中可以用,参数不需要加self,2种方法都可以
#super().sayHello()
print("hello...")
bosi = Bosi()
bosi.sayhello() halou...
hello...

2.5、私有属性不会被继承,公有属性会被继承

私有属性和私有方法只有在同一个类内部才能够继承,在外部不能继承

class 类1:
def 方法1(self):
self.属性1
self.__属性2
def __方法2(self):
self.方法1() #在相同类中的不同方法中,属性1可以继承,属性2也可以继承
def 方法3(self):
self.方法1() #因为是在同一个类中,所以方法1可以继承,包括公有方法1中的公有属性1和私有属性2
self.__方法2() #因为是在同一个类中,方法2可以继承 class 类2(类1): #继承类1
def 方法1(self):
self.属性1 #在不同类中公有属性1可以继承
self.__属性2 #在不同类中私有属性2不能继承
def 方法3(self):
self.方法1() #在不同类中公有方法1可以继承,包括公有方法1中的公有属性1和私有属性2
self.__方法2() #在不同类中私有方法2不能继承 aa = 类1()
bb = 类2()

类1中
  方法1是公有方法
    属性1是公有属性,在不同的方法和不同的类中都可以继承
    属性2是私有属性,在不同的类中不可以继承,在同一个类中不同方法中可以继承
  __方法2是私有方法,在同一个类中可以继承,在不同的类中不可以继承

day20-面向对象编程、继承的更多相关文章

  1. C++ Primer 学习笔记_69_面向对象编程 --继承情况下的类作用域

    面向对象编程 --继承情况下的类作用域 引言: 在继承情况下,派生类的作用域嵌套在基类作用域中:假设不能在派生类作用域中确定名字,就在外围基类作用域中查找该名字的定义. 正是这样的类作用域的层次嵌套使 ...

  2. Python 面向对象编程 继承 和多态

    Python 面向对象编程 继承 和多态 一:多继承性 对于java我们熟悉的是一个类只能继承一个父类:但是对于C++ 一个子类可以有多个父亲,同样对于 Python一个类也可以有多个父亲 格式: c ...

  3. Python面向对象编程——继承与派生

    Python面向对象编程--继承与派生 一.初始继承 1.什么是继承 继承指的是类与类之间的关系,是一种什么"是"什么的关系,继承的功能之一就是用来解决代码重用问题. 继承是一种创 ...

  4. Javascript 面向对象编程—继承和封装

      前  言 Javascript是一种基于对象(object-based)的语言,你遇到的所有东西几乎都是对象.但是,它又不是一种真正的面向对象编程(OOP)语言,因为它的语法中没有class(类) ...

  5. Javascript 进阶 面向对象编程 继承的一个样例

    Javascript的难点就是面向对象编程,上一篇介绍了Javascript的两种继承方式:Javascript 进阶 继承.这篇使用一个样例来展示js怎样面向对象编程.以及怎样基于类实现继承. 1. ...

  6. Javascript 进阶 面向对象编程 继承的一个例子

    Javascript的难点就是面向对象编程,上一篇介绍了Javascript的两种继承方式:Javascript 进阶 继承,这篇使用一个例子来展示js如何面向对象编程,以及如何基于类实现继承. 1. ...

  7. python面向对象编程 继承 组合 接口和抽象类

    1.类是用来描述某一类的事物,类的对象就是这一类事物中的一个个体.是事物就要有属性,属性分为 1:数据属性:就是变量 2:函数属性:就是函数,在面向对象里通常称为方法 注意:类和对象均用点来访问自己的 ...

  8. Py修行路 python基础 (十五)面向对象编程 继承 组合 接口和抽象类

    一.前提回忆: 1.类是用来描述某一类的事物,类的对象就是这一类事物中的一个个体.是事物就要有属性,属性分为 1:数据属性:就是变量 2:函数属性:就是函数,在面向对象里通常称为方法 注意:类和对象均 ...

  9. 【前端学习】javascript面向对象编程(继承和复用)

    前言       继承,代码复用的一种模式.和其它高级程序语言相比,javascript有点点不一样,它是一门纯面向对象的语言,在JS中,没有类的概念,但也可以通过原型(prototype)来模拟对象 ...

  10. CSIC_716_20191126【面向对象编程--继承】

    继承 什么是继承:继承是新建类的一种方式,通过此方式生成的类称为子类.或者 派生类,被继承的类称为父类.基类或超类.在python中,一个子类可以继承多个父类. 继承的作用:减少代码的冗余,提高开发效 ...

随机推荐

  1. SSM的配置文件

    Mybatis: SqlMapConfig.xml,配置了数据源,连接池,事务,加载sql映射文件(pojo),sqlsessionFactory对象,配置到spring容器中,mapeer代理对象或 ...

  2. Python——字符串2.0(实验)(python programming)

    直接打s,是程序员看到的:打print(),是用户看到的 列表 ] #列表索引,与数组唯一不同:等号左端可修改 转载自:https://www.cnblogs.com/wwwwwei/p/104816 ...

  3. 理解 neutron(15):Neutron Linux Bridge + VLAN/VXLAN 虚拟网络

    学习 Neutron 系列文章: (1)Neutron 所实现的虚拟化网络 (2)Neutron OpenvSwitch + VLAN 虚拟网络 (3)Neutron OpenvSwitch + GR ...

  4. Zabbix 告警内容配置

    #配置媒介告警类型 #----------------------------------------------------------------------------------------- ...

  5. MySQL学习----多版本并发mvcc

    MySQL中的大多数事务性存储引擎实现的都不是简单的行级锁.基于提升并发性能的考虑,他们一般实现了多版本并发控制(mvcc).不仅是mysql,包括oracle,postgresql等其他数据库也实现 ...

  6. Find the peace with yourself

    The purpose of being mature is to find the real calm and peace with yourself. Or you can say the tur ...

  7. 第11章 拾遗5:IPv6和IPv4共存技术(2)_ISATAP隧道技术

    6.3 ISATAP隧道技术 (1)基本概念 ①在一个IPv4网络中主机与路由器之间创建一条ISATAP隧道,以便让该主机可以访问IPv6网络中的资源. ②条件:IPv4中的PC主机需要支持IPv4和 ...

  8. 升级Android Studio到1.0.2的问题解决

    当前从光网下载到的Android Studio的版本是1.0.1,升级到1.0.2大概是3M的升级包.升级很简单,点击Help--Check For Update... 可是我碰到的情况是提示:Con ...

  9. 百度翻译API(C#)

    百度翻译开放平台:点击打开链接 1. 定义类用于保存解析json得到的结果 public class Translation { public string Src { get; set; } pub ...

  10. 外网访问内网的FTP服务器-原理解析

    1. 背景简介 最近研究如何在内网搭架FTP服务器,同时要保证外网(公网)能访问的到.终成正果,但走了一些弯路,在此记下,以飨后人. 2. 基础知识 FTP 使用 2 个端口,一个数据端口和一个命令端 ...