第五十节,面向对象基本介绍

一,面向对象基础1
c#、Java:只能用面向对象编程
Ruby、python、php:函数编程 + 面向对象

1.面向过程编程2
  就是程序最底层的实现过程
2.函数式编程3
  就是将最底层的实现过程封装到函数里,调用函数的方法编程
3面向对象编程4
  就是将若干函数封装到一个类里,调用类来实现里面的函数方法

 

注意:面向对象不是所有情况都适用 5

 

面向对象编程6
需要定义一个类 ,将功能函数写在类里,这样类里面的函数就叫做,实现一个类功能的方法,要使用这个类的方法时,创建这个类的对象赋值给一个变量,通过对象变量找到这个类下面的功能函数来实现(功能)的方法

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class fgjk: #定义一个类,在类里写函数来实现类的方法
    def f1(self,a): #方法1
        return a + 1
    def f2(self,b): #方法2
        pass
    def f3(self,c): #方法3
        pass

a1 = fgjk() #创建类对象赋值给一个变量
a2 = a1.f1(3) #调用类下面的一个函数传入参数,来实现一个功能,叫做方法
print(a2) #打印出这个方法的结果

#输出fgjk类下面的f1()方法
# 4

 

class关键字,定义一个类7

功能:定义一个类

使用方法:class 类名称:

格式:class fgjk:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class fgjk: #定义一个类,在类里写函数来实现类的方法
    def f1(self,a): #方法1
        return a + 1
    def f2(self,b): #方法2
        pass
    def f3(self,c): #方法3
        pass

 

定义好类后,将功能函数(方法)写在类里,注意:类里面的函数有一个必写值self8

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class fgjk: #定义一个类,在类里写函数来实现类的方法
    def f1(self,a): #方法1
        return a + 1
    def f2(self,b): #方法2
        pass
    def f3(self,c): #方法3
        pass

 

self是一个形式参数,这个形式参数是用来,在执行类方法时接收类对象返回值的,9

注意:类对象的返回值是由python自动当做实参,传入类方法函数的self,不需要我们写,由python自动完成

#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""定义类和类的方法"""
class fgjk: #定义一个类,在类里写函数来实现类的方法
    def f1(self,a): #方法1
        print("打印self接收的类对象值",self)
        return a #返回值
"""创建类的对象和是使用类的方法"""
a1 = fgjk() #创建类对象赋值给一个变量
print("打印类对象值",a1)
#注意:类对象的值是由python自动当做实参,传入类方法函数的,不需要我们写,由python自动完成,相当于下面写的a1.f1(a1,3)
a2 = a1.f1(3) #调用类下面的一个函数传入参数,来实现一个功能,叫做方法
print("打印返回值",a2) #打印出这个方法的结果

# 输出
# 打印类对象值 <__main__.fgjk object at 0x0000006685D37160>
# 打印self接收的类对象值 <__main__.fgjk object at 0x0000006685D37160>
# 打印返回值 3

 

定义好类和写好函数方法后,创建这个类的对象赋值给一个变量,通过变量找到这个类下面的功能函数来实现(功能)的方法  , 创建类对象也叫做(创建Foo类的实列)10

#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""定义类和类的方法"""
class fgjk: #定义一个类,在类里写函数来实现类的方法
    def f1(self,a): #方法1
        return a + 1
    def f2(self,b): #方法2
        pass
    def f3(self,c): #方法3
        pass

"""创建类对象和使用类的方法"""
a1 = fgjk() #创建类对象赋值给一个变量
a2 = a1.f1(3) #调用类下面的一个函数传入参数,来实现一个功能,叫做方法
print(a2) #打印出这个方法的结果

#输出fgjk类下面的f1()方法
# 4

 

面向对象原理图11

 

封装12

封装就是给对象封装普通字段

面向对象封装之,在类的对象里封装变量和变量值,非主流方法【不推荐】13
就是在类的对象里封装变量和变量值,封装后使用类函数方法时不需要传值,在类函数方法里通过self来获取类对象里的值即可

给类对象添加变量:创建对象变量.要添加的变量名称 = 变量值  如a1.zhi =  xx

类方法函数获取对象变量:在方法函数里通过接收对象的self来获取,self.添加的类对象变量名称,这样就可以获取到类对象的值

#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""面向对象封装之,给类对象封装变量和变量值"""
class fgjk: #定义一个类,在类里写函数来实现类的方法
    def f1(self): #方法1
        b = self.zhi + 5 #获取类对象里的zhi变量的值加5
        c = b + self.zhi2 #用b结果加类对象里的zhi2变量值
        return c
"""创建类的对象和使用类的方法"""
a1 = fgjk() #创建类对象赋值给一个变量
a1.zhi = 5 #给类对象封装一个变量和值
a1.zhi2 = 10 #给类对象封装一个变量和值
a2 = a1.f1() #执行类方法
print(a2) #打印出方法结果
# 输出
# 20

面向对象封装之,在类的对象里封装变量和变量值原理图14

 

__init__()构造方法,面向对象封装之,给类对象封装变量和变量值,主流方法 15

__init__(self)类方法函数,如果类里有定义__init__(self)类方法函数,创建对象后会自动执行__init__(self)方法函数的

使用方法:__init__(self,后面可以定义变量类接收对象传值然后封装到对象)

就是不在从类对象那里封装变量和值,从类的__init__(self)方法,向对象封装变量和值,因为只要创建对象后,python就会默认执行类的__init__(self)方法,然而对象的返回值是自动通过对象传值给类方法的self形式参数的,所以可以根据这个形式参数接收到的对象,向对象里封装变量和变量值

# -*- coding:utf-8 -*-
"""面向对象封装之,给类对象封装变量和变量值,主流方法"""
class fgjk: #定义一个类,在类里写函数来实现类的方法
    def __init__(self):
        print(self)
        self.adc = "你好" #通过self接收到的对象,向对象里封装变量和变量值
    def f1(self):
        print(self.adc)
"""创建类的对象和使用类的方法"""
a1 = fgjk() #创建类对象赋值给一个变量,并把类对象返回值传给类里面的方法函数的self形式参数
a1.f1() #执行类的方法函数
# 输出
# <__main__.fgjk object at 0x000000A5E652C518>
# 你好

通过类方法的self给对象封装变量原理图16

__init__()构造方法,面向对象封装之,给类对象封装变量和变量值,主流方法2【推荐】17

# -*- coding:utf-8 -*-
"""面向对象封装之,给类对象封装变量和变量值,主流方法"""
a = "变量值"
class fgjk: #定义一个类,在类里写函数来实现类的方法
    def __init__(self,b):
        print(self)
        self.adc = b #通过self接收到的对象,向对象里封装变量和变量值
    def f1(self):
        print(self.adc)
"""创建类的对象和使用类的方法"""
a1 = fgjk(a) #创建类对象赋值给一个变量,并把类对象返回值传给类里面的方法函数的self形式参数
a1.f1() #执行类的方法函数
# 输出
# <__main__.fgjk object at 0x000000A5E652C518>
# 变量值

主流方法2【推荐】原理图18

注意:我们一般都是用构造方法2

__del__(self)解释器销毁对象时自动调用,我们只需要知道一些就行,这是python自动完成的,叫做析构方法19

 

封装总结20

使用场景,当同一类型的方法具有相同参数时,直接封装到对象即可

使用场景2:把类当做模板,创建多个对象(每个对象内封装的数据可以不一样)

创建类对象,和__init__()构造封装对象变量,叫做初始化

给对象封装的变量,叫做给对象创建普通字段

 

继承21

继承就是在定义类b时,可以在b类名称后面加上()括号里写上另外一个a类的名称,这样b类就会继承a类里的方法22

1.子类(派生类)、继承父类(基类)中的所有功能23
2.Python类可以同时继承多个父类(基类)(c#/Java不可以)24

3.继承的优先级,继承里有相同方法的优先级25

  子类(派生类)、和父类(基类)同时存在一个方法是时,优先找子类(派生类),

  如果是一个类继承了多个类,而且继承的多个类中有同样的方法是,优先从子类(派生类)()括号里的父类(基类)左边优先

  如果是嵌套式继承,也就是一个类继承了多个基类,并且多个基类又继承了多个基类,这时是自己本身类优先,然后是上一级基类左边第一个优先,再者是左边第一个基类的上级基类优先,再者是左边第二基类优先以此类推

  也就是说,首先是自身优先,然后是基类左边优先,然后是基类左边深度优先,以此类推的

  如果嵌套式继承,最后有两个类都继承了同一个基类,这个被两个类继承的类不在深度查找,是最后查找这个类的

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class lei: #定义lei类
    def __init__(self,wb = ""): #接收定义lei对象里的传值
        self.wb = wb #将定义lei对象里的传值封装到lei对象里
    def f1(self):
        print("f1",self.wb) #打印f1和,lei对象里封装的wb变量
    def f2(self):
        print("f2")
    def f3(self):
        print("f3")

class lei2(lei): #定义lei2类并继承lei类的方法
    def __init__(self,wb2 = ""): #接收定义lei2对象里的传值
        self.wb2 = wb2 ##将定义lei2对象里的传值封装到lei2对象里
    def j1(self):
        print("j1")
    def j2(self):
        print("j2",self.wb2) #打印j2和,lei2对象里封装的wb2变量
    def j3(self):
        print("j3")

a = lei("你好") #创建lei类对象,并传值到lei类__init__方法
a.f1() #执行类里的f1()方法

b = lei2("我好") #创建lei2类对象,并传值到lei2类__init__方法
b.f3() #执行lei2类继承的lei里的f3()方法
b.j2() #执行lei2类里的j2()方法

# 输出
# f1 你好
# f3
# j2 我好

继承原理图26

 

继承优先级说明图27

自身优先图28

 

基类左边第一个优先图29

左边深度优先图30

 最后有两个类都继承了同一个基类,这个被两个类继承的类不在深度查找,是最后查找这个类的31

 

 

继承重点,self.XXX()继承容易错点,如果一个类继承了多个基类,并且基类里有self.XXX()方法,self实际就是创建的对象,self.xxx()就是又回到了创建对象的类里去找xxx()方法,如果创建的自身类里没有xxx()方法,就又从继承基类的左边第一个开始查找,在之深度等,以此按照前面说的优先级执行32

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class a: #定义a类
    def __init__(self,zhi = ""):
        self.zhi = zhi
    def f1(self):
        print("a")
class b: #定义b类
    def __init__(self,zhi = ""):
        self.zhi = zhi
    def b1(self):
        self.f1()
class c: #定义c类
    def __init__(self,zhi = ""):
        self.zhi = zhi
    def f1(self):
        print("c")
class d(b,c,a): #定义d类
    def __init__(self,zhi = ""):
        self.zhi = zhi
fsa = d("传值") #创建d类对象
fsa.b1() #执行d类对象的类里面的b1()方法,类里面没有b1方法,就到继承的基类左边第一个b类里去找b1方法,找到b1方法执行,然而b1里是执行的对象里面的f1方法,这样就又回到了d类里去找f1方法
# 输出
# c

self.XXX()继承原理图33

 

 

super()内置函数【推荐】,在一个类里获取上一级父类基类的,__init__方法里的对象封装值,注意只能获取上一级基类的__init__方法里的对象封装值34

使用方法:super(子类派生类名称,self).__init__()

格式:super(b,self).__init__()

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class c: #定义a类
    def __init__(self):
        self.zf = "狗shi"
    def f1(self):
        print("c")
class a: #定义a类
    def __init__(self):
        self.zhi = "动物"
    def f1(self):
        print("a")
class b(a): #定义b类
    def __init__(self):
        self.zh = ""
        super(b,self).__init__() #获取上一级父类基类的,__init__方法里的对象封装值
        print(self.zhi) #打印出获取到的,上一级父类基类的,__init__方法里的对象封装值
    def b1(self):
        print("b")
c = b()
c.f1()
# 输出
# 动物
# a

 

被获取类名称.__init__(self)在一个类里获取另外一个类的__init__方法里的对象封装值,注意,可以获取有继承关系的,也可以获取无继承关系的类35

使用方法:被获取类名称.__init__(self)

格式:c.__init__(self)

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class c: #定义a类
    def __init__(self):
        self.zf = "狗shi"
    def f1(self):
        print("c")
class a: #定义a类
    def __init__(self):
        self.zhi = "动物"
    def f1(self):
        print("a")
class b(a): #定义b类
    def __init__(self):
        self.zh = ""
        c.__init__(self) #在一个类里获取另外一个类的__init__方法里的对象封装值,注意,可以获取有继承关系的,也可以获取无继承关系的类
        print(self.zf) #打印获取到的,另外一个类的__init__方法里的对象封装值
    def b1(self):
        print("b")
c = b()
c.f1()
# 输出
# 狗shi
# a

 

多态36

多态就是多种形态

 

python自身支持多态
多态的简单理解就是,定义一个函数,创建类对象,把类对象当做实际参数传给函数的形式参数,在函数里通过形式参数接收到的类对象来执行对象类里的方法,也就是向函数传不同的对象,就执行不同对象类的方法

#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""多态,多种形态"""
class ab: #定义ab类
    def __init__(self,zhi = ""): #定义__init__方法接收类对象传的值
        self.zhi = zhi #将类对象传值封装到对象里吧,给对象封装一个字段
    def f1(self): #定义类方法
        print(self.zhi) #打印ab类对象里封装的zhi字段

class cd: #定义cd类
    def __init__(self,zhi = ""): #定义__init__方法接收类对象传的值
        self.zhi = zhi #将类对象传值封装到对象里吧,给对象封装一个字段
    def f1(self): #定义类方法
        print(self.zhi) #打印cd类对象里封装的zhi字段

def ef(fang): #定义一个函数,设置一个形式参数接收类对象
    fang.f1() #接收对象,并执行对象的类里面的f1()方法

ef(ab("你好")) #执行函数,创建ab类对象当做实参传值给ef函数
ef(cd("我好")) #执行函数,创建cd类对象当做实参传值给ef函数

# 输出
# 你好
# 我好

 多态原理图37

 

面向对象的进阶38

 

成员39
类下面的方法为类的成员
对象下面的封装字段为对象成员

利用反射来操作类里的成员40

hasattr()内置反射函数,到指定类查找指定方法是否存在,和到指定的对象下查找,对象下的封装变量是否存在,或者到指定对象查找对象类里的指定方法,存在返回True,否则返回False

注意:对象有对象指针指向了类,所有也能用hasattr()函数通过对象来查找类里的方法,所以推荐通过对象来查找,既可以查找类又可以查找对象下的字段

使用方法:hasattr(要查找的类名称或对象名称,字符串形式要查找的方法名称或对象封装名称)41

格式:hasattr(c,"f1")

到指定类查找指定方法是否存在

 

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class c: #定义a类
    def __init__(self):
        self.zf = "狗shi"
    def f1(self):
        print("c")
class a: #定义a类
    def __init__(self):
        self.zhi = "动物"
    def f1(self):
        print("a")
fa = hasattr(c,"f1") #hasattr()内置函数,到指定类查找指定方法是否存在,和到指定的对象下查找,对象下的封装变量是否存在,存在返回True,否则返回False
print(fa)
# 输出
# True

 

到指定的对象下查找对象下的封装变量是否存在

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class c: #定义a类
    def __init__(self):
        self.zf = "狗shi"
    def f1(self):
        print("c")
class a: #定义a类
    def __init__(self):
        self.zhi = "动物"
    def f1(self):
        print("a")
fa = hasattr(a(),"zhi") #hasattr()内置函数,到指定类查找指定方法是否存在,和到指定的对象下查找,对象下的封装变量是否存在,存在返回True,否则返回False
print(fa) 
# 输出
# True

到指定对象查找对象类里的指定方法

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class c: #定义a类
    def __init__(self):
        self.zf = "狗shi"
    def f1(self):
        print("c")
class a: #定义a类
    def __init__(self):
        self.zhi = "动物"
    def f1(self):
        print("a")
fa = hasattr(a(),"f1") #hasattr()内置函数,到指定类查找指定方法是否存在,和到指定的对象下查找,对象下的封装变量是否存在,存在返回True,否则返回False
print(fa)
# 输出
# True

 

getattr()内置反射函数,到指定的对象下找到,对象下的封装变量赋值给一个变量,或者到指定对象找到对象类里的指定方法赋值给一个变量42

注意:对象有对象指针指向了类,所有也能用hasattr()函数通过对象来查找类里的方法,所以推荐通过对象来查找,既可以查找类又可以查找对象下的字段

使用方法:getattr(要查找的对象,字符串形式要查找的方法名称或对象封装名称)

格式:fa = getattr(c(),"f1")

到指定对象找到对象类里的指定方法赋值给一个变量,并执行方法

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class c: #定义a类
    def __init__(self):
        self.zf = "狗shi"
    def f1(self):
        print("c")
class a: #定义a类
    def __init__(self):
        self.zhi = "动物"
    def f1(self):
        print("a")
fa = getattr(c(),"f1") #getattr()内置反射函数,到指定的对象下找到,对象下的封装变量赋值给一个变量,或者到指定对象找到对象类里的指定方法赋值给一个变量
fa() #执行找到的类方法
# 输出
# c

到指定的对象下找到,对象下的封装变量赋值给一个变量

#!/usr/bin/env python
# -*- coding:utf-8 -*-
class c: #定义a类
    def __init__(self):
        self.zf = "狗shi"
    def f1(self):
        print("c")
class a: #定义a类
    def __init__(self):
        self.zhi = "动物"
    def f1(self):
        print("a")
fa = getattr(c(),"zf") #getattr()内置反射函数,到指定的对象下找到,对象下的封装变量赋值给一个变量,或者到指定对象找到对象类里的指定方法赋值给一个变量
print(fa)
# 输出
# 狗shi

 

用反射操作面向对象成员43

根据字符串方式的面向对象模块,和字符串方式的类方法,用反射来执行面向对象44

面向对象模块

#!/usr/bin/env python
# -*- coding:utf8 -*-
class c: #定义a类
    def __init__(self):
        self.zf = "狗shi"
    def f1(self):
        print("c")
class a: #定义a类
    def __init__(self):
        self.zhi = "动物"
    def f1(self):
        print("a222")

反射操作面向对象模块里的成员

#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""根据字符串方式的面向对象模块,和字符串方式的类方法,用反射来执行面向对象"""
a = "lib.ska.mk"    #面向对象模块路径
b = "f1"            #类方法名称
c = __import__(a,fromlist=True)     #反射方式导入面向对象模块
d = hasattr(c.a(),b)                #查找模块里的a类里是否有f1方法,返回布尔值
if d:                               #判断模块里的a类里是否有f1方法
    f1 = getattr(c.a(),b)           #如果有就找到f1方法赋值给一个变量
    f1()                            #执行找到a类里的f1方法
else:
    print("a类里没有f1方法")

# 输出
# a222

 

静态字段45

静态字段,也就是在类里面定义变量,提供类里的所有方法调用,这样能很好的实现多个类有一个相同数据的情况46

注意:静态字段是通过,类名称.静态字段名称来访问的,对象封装的普通字段,是通过self.普通字段名称来访问的

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定义a类
    shux = "动物"
    def __init__(self,zhu): #初始化__init__接收对象传值
        self.zhu = zhu #将对象传值封装到对象里
    def f1(self): #定义方法
        print(a.shux, self.zhu) #打印类的静态字段和对象封装的普通字段
    def f2(self): #定义方法
        print(a.shux, self.zhu) #打印类的静态字段和对象封装的普通字段
    def f3(self): #定义方法
        print(a.shux, self.zhu) #打印类的静态字段和对象封装的普通字段
s = a("") #创建对象并传值
s.f1() #执行对象类里的f1()方法
f = a("") #创建对象并传值
f.f2() #执行对象类里的f2()方法
b = a("") #创建对象并传值
b.f3() #执行对象类里的f3()方法
# 输出
# 动物 猫
# 动物 狗
# 动物 猪

静态字段原理图47

 

静态方法48

就是在类里定义普通函数,函数上面用上装饰符@staticmethod,静态方法不需要传self参数,静态方法通过类来访问,不需要创建对象就可以访问

@staticmethod在类里声明一个静态方法49

 

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定义a类
    def __init__(self,zhu): #初始化__init__接收对象传值
        self.zhu = zhu #将对象传值封装到对象里
    @staticmethod #定义静态方法
    def f1(): #静态方法
        print("静态方法")
    def f3(self): #定义方法
        print(a.shux, self.zhu)
a.f1()
# 输出
# 静态方法

 

静态方法原理图50

 

类方法51

就是在类里定义一个函数,函数上面用上装饰符@classmethod,函数里有一个必写形式参数cls用来接收类名称

@classmethod在类里声明一个类方法52

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定义a类
    def __init__(self,zhu): #初始化__init__接收对象传值
        self.zhu = zhu #将对象传值封装到对象里
    @classmethod #定义类方法
    def f1(cls): #自动将类名称传值给cls形参
        print(cls) #打印cls接收到的类名称
    def f3(self): #定义方法
        print(a.shux, self.zhu)
a.f1()
# 输出
# <class '__main__.a'>

类方法原理图53

 

特性方法54

@property特性方法55

就是在类里定义一个普通方法函数,函数上面用上装饰符@property,函数里有一个必写形式参数self用来接收对象地址,也可以给方法封装普通字段

特性方法与普通方法的区别:就是执行特性方法函数时不用写()括号,特性方法就是将普通方法伪造成通过对象获取的字段,特殊方法获取到返回值后是可以重新赋值的

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定义a类
    def __init__(self,zhu): #初始化__init__接收对象传值
        self.zhu = zhu #将对象传值封装到对象里
    @property #声明特性方法
    def f1(self): #定义特性方法
        te = "{}方法".format(self.zhu)
        print(te)
    def f3(self): #定义方法
        print(a.shux, self.zhu)
s = a("特性")
s.f1 #执行对象类里的f1特性方法
# 输出
# 特性方法
s.f1 = "重新赋值" #特殊方法获取到返回值后是可以重新赋值的

特性方法原理图56

 

设置特性方法:就是给特性方法设置值57

@方法名称.setter给特性方法设置值58

就是在类里的特性方法下面,写一个给特性方法名称一样的方法函数,函数上面用上装饰符@方法名称.setter,在方法里设置一个形式参数来接收,执行设置特性方法传值,执行设置特性方法时,将特性方法 = 要设置的值即可

 

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定义a类
    def __init__(self,zhu): #初始化__init__接收对象传值
        self.zhu = zhu #将对象传值封装到对象里
    @property #声明特性方法
    def f1(self): #定义特性方法
        te = "{}方法".format(self.zhu)
        print(te)
    @f1.setter  #设置特性方法
    def f1(self,v): #设置特性方法
        print(v) #打印设置的特性方法值
        self.zhu = v #将设置的特性方法值替换对象封装的普通字段
s = a("特性")
s.f1 #执行对象类里的f1特性方法
s.f1 = "设置特性方法值"
s.f1
# 输出
# 特性方法
# 设置特性方法值
# 设置特性方法值方法

 设置特性方法原理图59

 

成员修饰符60
修饰成员的使用权限对成员:静态字段、普通字段、普通方法、静态方法、类方法、特性方法,进行成员权限修饰61
  公有:就是没加__修饰符的成员,既可以在类里面访问,也可以通过类或者对象外部访问
  私有:就是加上__修饰符的成员,通过对象或者类无法外部访问,只能在类内部访问,外部要想访问必须在类的内部定义一个公有方法,在公有方法里执行要想访问的私有成员,通过公有方法来间接的访问私有成员,注意:一个类的私有方法只有类自己内部可以使用, 而且无法被继承。

 

__类成员修饰符,用于修饰类的成员私有权限,用了__修饰符的私有成员只有类自身内部可以访问。62

 静态字段修饰符63

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定义a类
    __jt = "静态字段"
    def __init__(self,zhu = ""): #初始化__init__接收对象传值
        self.zhu = zhu #将对象传值封装到对象里
    def f1(self):
        print(a.__jt)
    def f2(self):
        pass
#print(a.__jt) #静态字段加修饰符后外部不可以访问
f = a() #定义对像
f.f1() #可以通过类里的f1方法间接访问
# 输出
# 静态字段

普通字段修饰符64

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定义a类
    def __init__(self,zhu = ""): #初始化__init__接收对象传值
        self.__zhu = zhu #将对象传值封装到对象里,封装普通字段
    def f1(self):
        print(self.__zhu)
    def f2(self):
        pass
f = a("普通字段") #定义对象
#print(f.zhu) #普通字段加修饰符后外部不可以访问
f.f1() #通过类里的f1方法可以间接访问对象里封装的普通字段
# 输出
# 普通字段

普通方法修饰符65

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定义a类
    def __init__(self,zhu = ""): #初始化__init__接收对象传值
        self.__zhu = zhu #将对象传值封装到对象里,封装普通字段
    def __f1(self):
        print("普通方法")
    def f2(self):
        self.__f1()
f = a() #定义对象
#f.__f1() #普通方法加修饰符后外部不可以访问
f.f2() #通过类里的f2方法可以间接访问加修饰符的f1普通方法
# 输出
# 普通方法

静态方法修饰符66

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定义a类
    def __init__(self,zhu = ""): #初始化__init__接收对象传值
        self.__zhu = zhu #将对象传值封装到对象里,封装普通字段
    @staticmethod #定义静态方法
    def __f1():
        print("静态方法")
    def f2(self):
        a.__f1()
#a.__f1() #静态方法加修饰符后外部不可以访问
f = a() #定义对象
f.f2() #通过类里的f2方法可以间接访问加修饰符的f1静态方法
# 输出
# 静态方法

类方法修饰符67

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定义a类
    def __init__(self,zhu = ""): #初始化__init__接收对象传值
        self.__zhu = zhu #将对象传值封装到对象里,封装普通字段
    @classmethod #定义类方法
    def __f1(cls):
        print("类方法",cls)
    def f2(self):
        a.__f1()
#a.__f1() #类方法加修饰符后外部不可以访问
f = a() #定义对象
f.f2() #通过类里的f2方法可以间接访问加修饰符的f1类方法
# 输出
# 类方法 <class '__main__.a'>

特性方法修饰符68

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定义a类
    def __init__(self,zhu = ""): #初始化__init__接收对象传值
        self.__zhu = zhu #将对象传值封装到对象里,封装普通字段
    @property #定义特性方法
    def __f1(self):
        print("特性方法")
    def f2(self):
        self.__f1
f = a() #定义对象
#f.__f1 #特性方法加修饰符后外部不可以访问
f.f2() #通过类里的f2方法可以间接访问加修饰符的f1特性方法
# 输出
# 特性方法

成员修饰符之特殊手段,外部访问类的私有成员【不到万不得已不使用】69

方法:类名称或者对象名称._类名称__私有字段名称

格式:a._a__jt

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定义a类
    __jt = "静态字段"
    def __init__(self,zhu = ""): #初始化__init__接收对象传值
        self.zhu = zhu #将对象传值封装到对象里
    def f1(self):
        print(a.__jt)
    def f2(self):
        pass
print(a._a__jt) #特殊手段外部访问类的私有成员
# 输出
# 静态字段

 

类成员之特殊方法70

__call__方法是类里的一个特殊方法,当类里定义了这个方法时,创建对象后在对象后面加上()括号,也可以在对象变量后面加括号是一样的,会自动执行类里的__call__方法71

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定义a类
    def __init__(self,zhu = ""): #初始化__init__接收对象传值
        self.zhu = zhu #将对象传值封装到对象里
    def __call__(self, args): #定义__call__方法
        print(args,self.zhu)
    def f2(self):
        pass
f = a("方法")("__call__")
# 输出
# __call__ 方法
#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定义a类
    def __init__(self,zhu = ""): #初始化__init__接收对象传值
        self.zhu = zhu #将对象传值封装到对象里
    def __call__(self, args): #定义__call__方法
        print(args,self.zhu)
    def f2(self):
        pass
f = a("方法")
f("__call__")
# 输出
# __call__ 方法

 

__getitem__方法是类里的一个特殊方法,当类里定义了这个方法时,创建对象后在对象后面加上[]中括号,会自动执行类里的__getitem__方法,并将[]中括号里的值传给__getitem__方法的形式参数。72

注意:对象后面加上[1:2:3],也是执行类的__getitem__方法

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定义a类
    def __init__(self,zhu = ""): #初始化__init__接收对象传值
        self.zhu = zhu #将对象传值封装到对象里
    def __getitem__(self, item): #创建__getitem__方法
        s = self.zhu + item #将创建对象封装的普通字段,加上执行__getitem__方法时的传值,相加后并返回值
        return s #返回值
    def f2(self):
        pass
f = a(10) #创建对象传值
b = f[10] #执行__getitem__方法并传值给__getitem__方法
print(b) #打印__getitem__方法返回值
# 输出
# 20

 

对象后面加上[1:2:3],也是执行类的__getitem__方法 73

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定义a类
    def __init__(self,zhu = ""): #初始化__init__接收对象传值
        self.zhu = zhu #将对象传值封装到对象里
    def __getitem__(self, item): #创建__getitem__方法,将[]中括号里的数据重新封装成一个slice对象传给item
        print(item) #打印接收到的slice对象元素
    def f2(self):
        pass
f = a() #创建对象传值
b = f[10:12:3] #执行__getitem__方法并传值给__getitem__方法
print(b) #打印__getitem__方法返回值
# 输出
# 20

 

__setitem__方法是类里的一个特殊方法,当类里定义了这个方法时,创建对象后在对象后面加上[xxx]=xxx中括号等于,会自动执行类里的__setitem__方法,并将[xxx]=xxx中括号和等于里的值传给__setitem__方法的形式参数74

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定义a类
    def __init__(self,zhu = ""): #初始化__init__接收对象传值
        self.zhu = zhu #将对象传值封装到对象里
    def __setitem__(self, key, value): #定义__setitem__方法
        print(key,value) #打印[xxx] = xxx 传值
    def f2(self):
        pass
f = a() #创建对象传值
f[""] = "" #执行__setitem__方法并传值给__setitem____方法
# 输出
# 键 值

 

__delitem__方法是类里的一个特殊方法,当类里定义了这个方法时,创建对象后在对象后面加上del对象名称[xxx]中括号,会自动执行类里的__delitem__方法,并将[xxx]中括号里的值传给__delitem__方法的形式参数75

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定义a类
    def __init__(self,zhu = ""): #初始化__init__接收对象传值
        self.zhu = zhu #将对象传值封装到对象里
    def __delitem__(self, key): #定义__delitem__方法
        print("删除",key) #操作[xxx]里传来的值
    def f2(self):
        pass
f = a() #创建对象传值
del f[""] #执行__delitem__方法,并传值给__delitem__方法
# 输出
# 删除 键

 

__iter__方法是类里的一个特殊方法,当类里定义了这个方法时,创建对象后只要for循环对象,会自动执行类里的__iter__方法,如__iter__方法里是一个生成器,for循环就会循环出生成器里的结果76

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定义a类
    def __iter__(self): #定义__iter__方法
        yield 1 #生成器
        yield 2
        yield 3
        yield 4
    def f1(self):
        pass
s = a() #创建对象
for i in s: #循环对象
    print(i) #循环打印出生成器里的数据
# 输出
# 1
# 2
# 3
# 4

 

__str__方法是类里的一个特殊方法,当类里定义了这个方法时,创建对象后只要print打印对象或者str(对象)时就,会自动执行类里的__str__方法77

 

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定义类
    def __init__(self,vas): #定义__init__方法,接收对象传值
        self.fds = vas #将对象传值封装成对象普通字段
    def __str__(self): #定义__str__方法
        return self.fds #返回对象里的普通字段
    def f1(self):
        pass
f = a("str方法")
print(f) #打印对象时自动执行__str__方法

b = str(f) #str(对象)时也会执行__str__方法
print(b)
# 输出
# str方法
# str方法

 

 

__dict__查看对象或者类里的成员78

#!/usr/bin/env python
# -*- coding:utf8 -*-
class a: #定义a类
    def __init__(self,zhu = ""): #初始化__init__接收对象传值
        self.zhu = zhu #将对象传值封装到对象里
    def __getitem__(self, item): #创建__getitem__方法,将[]中括号里的数据重新封装成一个slice对象传给item
        print(item) #打印接收到的slice对象元素
    def f2(self):
        pass
f = a("zhi") #创建对象传值
print(f.__dict__) #查看对象里的成员
print(a.__dict__) #查看类里的成员
# 输出
# {'zhu': 'zhi'}
# {'__init__': <function a.__init__ at 0x00000036345AE510>, 'f2': <function a.f2 at 0x00000036345AE620>, '__getitem__': <function a.__getitem__ at 0x00000036345AE598>, '__weakref__': <attribute '__weakref__' of 'a' objects>, '__dict__': <attribute '__dict__' of 'a' objects>, '__module__': '__main__', '__doc__': None}

 

可以忽略,源码创建类原理79

 __new__ python创建类源码方法80

 __metaclass__ python创建类源码方法81

阅读以下代码:

class Foo(object):
 
    def __init__(self):
        pass
 
obj = Foo()   # obj是通过Foo类实例化的对象

上述代码中,obj 是通过 Foo 类实例化的对象,其实,不仅 obj 是一个对象,Foo类本身也是一个对象,因为在Python中一切事物都是对象

如果按照一切事物都是对象的理论:obj对象是通过执行Foo类的构造方法创建,那么Foo类对象应该也是通过执行某个类的 构造方法 创建。

print type(obj) # 输出:<class '__main__.Foo'>     表示,obj 对象由Foo类创建
print type(Foo) # 输出:<type 'type'>              表示,Foo类对象由 type 类创建

所以,obj对象是Foo类的一个实例Foo类对象是 type 类的一个实例,即:Foo类对象 是通过type类的构造方法创建。

那么,创建类就可以有两种方式:

普通方式

class Foo(object):
 
    def func(self):
        print 'hello wupeiqi'

特殊方式(type类的构造函数)

def func(self):
    print 'hello wupeiqi'
 
Foo = type('Foo',(object,), {'func': func})
#type第一个参数:类名
#type第二个参数:当前类的基类
#type第三个参数:类的成员

==》 类 是由 type 类实例化产生

那么问题来了,类默认是由 type 类实例化产生,type类中如何实现的创建类?类又是如何创建对象?

答:类中有一个属性 __metaclass__,其用来表示该类由 谁 来实例化创建,所以,我们可以为 __metaclass__ 设置一个type类的派生类,从而查看 类 创建的过程。

class MyType(type):

    def __init__(self, what, bases=None, dict=None):
        super(MyType, self).__init__(what, bases, dict)

    def __call__(self, *args, **kwargs):
        obj = self.__new__(self, *args, **kwargs)

        self.__init__(obj)

class Foo(object):

    __metaclass__ = MyType

    def __init__(self, name):
        self.name = name

    def __new__(cls, *args, **kwargs):
        return object.__new__(cls, *args, **kwargs)

# 第一阶段:解释器从上到下执行代码创建Foo类
# 第二阶段:通过Foo类创建obj对象
obj = Foo()

 

重点总结82

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

成员:84
字段:普通字段(每个对象都有一份相同数据时)、静态字段(每个对象都不同的数据时)
方法:静态方法(无需使用对象封装的内容时)、类方法(需要获取对象名称时)、普通方法(使用对象中的数据时)
特性方法:特性方法(将方法伪造成字段时)
特殊方法:对象后写上执行属性,就会自动执行特殊方法

类成员访问方法:85
通过类访问的有:静态字段,静态方法,类方法
通过对象访问的有:普通字段,普通方法,特性方法
一般有self的方法用对象访问,无self的方法用类来访问

成员修饰符:86
修饰成员的使用权限对成员:静态字段、普通字段、普通方法、静态方法、类方法、特性方法,进行成员权限修饰
公有:就是没加__修饰符的成员,既可以在类里面访问,也可以通过类或者对象外部访问
私有:就是加上__修饰符的成员,通过对象或者类无法外部访问,只能在类内部访问,外部要想访问必须在类的内部定义一个公有方法,在公有方法里执行要想访问的私有成员,通过公有方法来间接的访问私有成员
,注意:一个类的私有方法只有类自己内部可以使用,而且无法被继承。

特殊方法对应的执行属性:87
类名称(xxx):创建对象并执行类的__init__方法
对象变量(xxx):执行类的__call__方法
对象变量[xxx]:执行类的__getitem__方法
对象变量[x:x:x]:执行类的__getitem__方法
对象变量[xxx]=xxx:执行类的__setitem__方法
del对象变量[xxx]:执行类的__delitem__方法
for循环对象变量:执行类的__iter__方法

posted @ 2016-09-16 15:39  林贵秀  阅读(367)  评论(0编辑  收藏  举报