python面向对象

面向对象和面向过程

面向对象的三个主要特征:封装、继承、多态。

面向过程编程:函数式编程,C程序等

面向对象编程:C++,JAVA,Python等

类和对象

类和对象是面向对象中的两个很重要的概念。

类:是对事物的抽象,比如 人类、球类。类还有属性:比如人的眼耳口鼻。还有方法:吃穿住行。静态属性,动态方法。

对象:是对类的一个实例,比如足球、篮球

面向对象的主要思想:封装、继承、多态。这种思想方便解决较为复杂的项目,且维护起来较为容易。

python类的定义:

数字字母下划线组成的,不能以数字开头。定义变量是小写,两个单词则是下划线连接。函数的话则是第二个单词之后是大写字母开头。类的话是每个首字母大写。这样定义根据名称就可以知道是函数还是类。

类把需要的变量和函数组合成一起,这种包含成为”封装“。" class A(object): "

类的结构:

class类名:

    成员变量 - 属性

    成员函数 - 方法

通过对象访问属性:color是属性,所以后面没有括号

#@File :demo_lei.py
class People(object):
    color = 'yellow'            \这也是静态属性
ren = People()
print ren
print ren.color
<__main__.People object at 0x02CC9FD0>  \返回值带尖括号的,就是类
yellow                   \通过对象访问属性的返回值
类的定义

定义动态方法:方法中至少有一个参数是self。调用方法时,需要加括号。

#@File :demo_lei.py
class People(object):
    color = 'yellow'
    def think(self):
        print "I am a thinker"
ren = People()
ren.think()                            \方法的调用需要使用括号。
返回值
I am a thinker

  实例化:把类赋值给变量,变量的类型就是一个对象。通过对象访问类里面的属性和方法。

类的属性:

首先:对象的创建

创建对象的过程称之为实例化;当一个对象被创建之后,包含三个方面的特性:对象句柄、属性和方法。句柄用于区分不同的对象。对象的属性和方法与类中的成员变量和成员函数对应。

类的属性:类的属性按使用范围分为公有属性和私有属性,类的属性范围取决于属性的名称。

公有属性:在类中和类外都能调用的属性。

私有属性:不能再类外及类意外的函数调用。定义方式:以“__”双下划线开始的成员变量就是私有属性。可以通过instance._classname__attribute方式访问。

内置属性:由系统在定义类到时候默认添加的,由前后双下划线构成,__dict__,__module__。

#@File :demo_lei.py
class People(object):
    color = 'yellow'
    __age = 20
    def think(self):
        print "I am a thinker"
        print self.__age
ren = People()
ren.think()
print ren.__age

I am a thinker
Traceback (most recent call last):
20
  File "C:/Users/xiaojingjing/PycharmProjects/untitled1/liziyan/demo_lei.py", line 18, in <module>
    print ren.__age
AttributeError: 'People' object has no attribute '__age'
对象创建

这里就是私有属性的创建及调用。

 !!!测试过程中可以使用这种方法:私有属性就是为了保护仅在内部调用,所以在正常程序中不建议这么使用。

print ren._People__age      可以正常打印出返回值!

 当类实例化之后,可以通过实例过后的对象  对类的属性进行修改

 

#@File :demo_lei.py
class People(object):
    color = 'yellow'
    __age = 20
    def think(self):
        print "I am a thinker"
        print self.__age
ren = People()
ren.think()
print ren.__dict__
print People.__dict__
返回值:
I am a thinker
20
{}    \这里与预期有出入,至少应该返回:{’color‘: ’yellow‘}的,问题没有找到。
{'__module__': '__main__', 'color': 'yellow', '__doc__': None, '__dict__': <attribute '__dict__' of 'People' objects>, '_People__age': 20, '__weakref__': <attribute '__weakref__' of 'People' objects>, 'think': <function think at 0x034278F0>}

    

  

类的方法:

方法的定义和函数一样,但是需要self作为第一个参数。与类的属性类似,类的方法有:公有方法、私有方法、类方法、静态方法。

 共有方法:在类中和类外都能调用的方法。

私有方法:不能被类的外部调用,在方法前面加上”__“双下划线就是私有方法。

self参数:用于区分函数和类的方法(必须有一个self),self参数表示执行对象本身。

 类方法 -- 动态方法:被classmethod()函数处理过的函数,能被类所调用,也能被对象所调用(是继承的关系)

通过类访问访问其中的方法,称为动态方法:通过类访问方法占用的资源是少的,因为除了调用需要的方法(self以及其他在该方法中定义的属性操作等)外,其他的方法是不会被加载的。

如果需要直接使用类名来调用方法而不借助实例对象,可以使用classmethod函数实现,方法如下:
#@File :demo_lei.py
class People(object):
    color = 'yellow'
    __age = 20
    def test(self):
        print "Testing..."
    cm = classmethod(test)
jack = People()
People.cm()
People.test()

Testing...
Traceback (most recent call last):
  File "C:/Users/xiaojingjing/PycharmProjects/untitled1/liziyan/demo_lei.py", line 24, in <module>
    People.test()
TypeError: unbound method test() must be called with People instance as first argument (got nothing instead)
动态方法

静态方法:相当于“全局变量“,可以被类直接调用,可以被所有实例化对象共享,通过staticmethod()定义,静态方法没有”self"参数

首先设置静态方法的方式是:定义的时候不需要使用self参数,但是需要staticmethod函数处理。

#@File :demo_lei.py
class People(object):
    color = 'yellow'
    __age = 20
    def test():
        print "Testing..."
    sm = staticmethod(test)
jack = People()
People.sm()

Testing...
静态方法

通过上述两个例子看出动态方法与静态方法的输出是一样的,但是其中的运行机制却是不同的:

动态方法是需要谁才会加载谁到内存中,所以是省资源但是效率低;静态方法因为没有(self)所以加载时就会加载所有的方法,占资源但是执行效率高。

 当静态方法需要调用类中的其他成员:

#@File :demo_lei.py
class People(object):
    color = 'yellow'
    __age = 20
    def static():
        print "This is static"
        print People.color
    def dongtai(self):
        print 'this is dongtailei'
        print self.color
    cm = classmethod(dongtai)
    sm = staticmethod(static)
jack = People()
People.sm()
People.cm()

This is static
yellow
this is dongtailei
yellow

  除了使用以上说的两个函数来处理动态方法静态方法,还可以使用装饰器:

装饰器:

 装饰器也可以自己写,这里暂时没有涉及。简单学会使用即可。

    @classmethod            #装饰器表示这个方法可以被类调用
    def classFun(self):
        print self.name,
        print "我是类方法"
    @staticmethod
    def staticFun():        #静态方法与动态方法不同,定义时不需要使用self
        print MyClass.name,
        print "我是静态方法"

使用装饰器使得该方法可以被调用。
装饰器

python内部类:

内部类就是类的嵌套:在类里面再创建类。

#@File :demo_lei.py
class People(object):
    color = 'yellow'
    __age = 20

    class Chinese(object):
        print 'I am Chinese'
        name = 'zhe shi neibulei shuxing'

jack = People()         \这里也可以直接实例化对象为jack = People.Chinese,之后直接打印jack.name
print jack.Chinese.name

I am Chinese
zhe shi neibulei shuxing
内部类的使用

__str__:类似这样的双下划线开头结尾的成为类的内置方法或魔术方法。

#@File :demo_lei.py
class People(object):
    color = 'yellow'
    __age = 20

    # def __str__(self):
    #     return "this is People-class"

    class Chinese(object):
        print 'I am Chinese'
        name = 'zhe shi neibulei shuxing'

ren = People()
print ren

I am Chinese
<__main__.People object at 0x037D9030>
可见这里的显示并不友好,可以对代码进行修改:上述代码注释部分打开后重新执行:
I am Chinese
this is People-class

  

构造函数和析构函数:

构造函数:用于初始化类的内部状态,python提供的构造函数是:__init__();该方法是可选的,如果不提供,python会给出一个默认的 __init__方法。

析构函数:用于释放对象占用的资源,python提供的析构函数是__del__();该函数也是可选的,如果不提供,则python会在后台提供默认的析构函数。

#@File :demo_lei.py
class People(object):
    color = 'yellow'
    __age = 20
    def __str__(self):
        return "this is People-class"
    def __init__(self):
        self.color = 'black'
    class Chinese(object):
        print 'I am Chinese'
        name = 'zhe shi neibulei shuxing'
ren = People()
print ren.color
print People.color

I am Chinese
black
yellow
这里看出构造函数也是不需要调用自动执行的,触发执行则是通过实例化对象实现的。如果不实例化对象,直接使用类调用,则不会触发初始化。
构造函数

初始化函数不仅可以放属性,还可以放方法:

#@File :demo_lei.py
class People(object):
    color = 'yellow'
    __age = 20
    def __str__(self):
        return "this is People-class"
    def __init__(self, c='white'):
        self.color = c
        self.think()
    def think(self):
        print ('I am a thinker')
    class Chinese(object):
        # print 'I am Chinese'
        name = 'zhe shi neibulei shuxing'
ren = People('green')
print ren.color
print People.color

I am a thinker
green
yellow
初始化函数里放方法

析构函数:脚本结束之后才会执行,主要是释放资源。其实即使没有这个函数,python中还有个垃圾回收机制

#@File :demo_lei.py
class People(object):
    color = 'yellow'
    __age = 20
    def __init__(self, c='white'):
        self.color = c
        self.fd = open('C:YouKuAaa.txt')
    def __del__(self):
        print 'Del...'
        self.fd.close()

ren = People()
print People.color
print 'main end'

yellow
main end
Del...
析构函数调用的时间

由上面脚本可以看出 __del__ 结束之后才会执行,主要是释放资源。其实即使没有这个函数,python中还有个垃圾回收机制。

 python的垃圾回收站机制:

 python采用垃圾回收机制来清理不再使用的对象;python提供gc模块释放不再使用的对象

python采用“引用计数”的算法方式来处理回收,即:当某个对象在其作用域中不再被其他对象引用的时候,python就自动清除对象;

gc模块的collect()可以一次性收集所有待处理的对象(gc.collect)

#@File :demo_lei.py
import gc
class People(object):
    color = 'yellow'
    __age = 20
    def __init__(self, c='white'):
        self.color = c
        self.fd = open('C:YouKuAaa.txt')
    def __del__(self):
        print 'Del...'
        self.fd.close()
print gc.collect()
ren = People()
print People.color
print 'main end'

0
yellow
main end
0
Del...
gc.collect()

该模块方法的返回值为0则为没有需要回收的文件。这个模块在后台做清理工作,所以这部分一般不需要我们再关心了。

类的继承:

继承是面向对象的重要特性之一;

继承关系:是相对两个类而言的父子关系,子类继承了父类的所有共有属性和方法。

继承实现了代码的重用。

继承可以重用已经存在的数据和行为,减少代码的重复编写。python再类名后使用一对括号来表示继承关系,括号中的类即为父类。

#@File :demo_lei.py
import gc
class People(object):
    color = 'yellow'
    def __init__(self, c):
        print "Init..."
        self.dwell = 'Earth'
    def think(self):
        print "I am a %s" % self.color
        print "I am a thinker"
class Chinese(People):
    def __init__(self):
        People.__init__(self, 'red')
    pass
cn = Chinese()

Init...
类的继承

格式:class Myclass(ParentClass)

这里的重点:父类定义了 __init__方法(我理解是父类对__init__方法进行了加工,不是采用__init__默认的格式,不然没必要重新定义所以),子类必须显式调用父类的 __init__方法:ParentClass.__init__(self, [args...])如果子类需要扩展父类的行为,可以添加 __init__方法的参数。注意定义父类时,要使用class Parent(object),new style方式来定义,否则继承会报错。

还可以使用super函数继承父类:这里需要牢记super的语法格式结构!

#@File :demo_lei.py
import gc
class People(object):
    color = 'yellow'
    def __init__(self, c):
        print "Init..."
        self.dwell = 'Earth'
class Chinese(People):
    def __init__(self):
        # People.__init__(self, 'red')
        super(Chinese, self).__init__('red')
    pass
cn = Chinese()

Init...
使用super继承父类继承__init__

继承__init__初始化函数更推荐使用super来进行类的集成,因为super有很大的优势:自动识别到父类不需要手动输入父类名称,如果修改父类名称,可以省略很多工作量。

有了父类,子类中可以节省代码重复,还可以增加自己需要的方法

#@File :demo_lei.py
import gc
class People(object):
    color = 'yellow'
    def __init__(self, c):
        print "Init..."
        self.dwell = 'Earth'
    def think(self):
        print "This is Parent`s think"
class Chinese(People):
    def __init__(self):
        # People.__init__(self, 'red')
        super(Chinese, self).__init__('red')
    def talk(self):
        print "I like talking"
    # def think(self):
    #     print "child`s think"
cn = Chinese()
cn.talk()
cn.think()

Init...
I like talking
This is Parent`s think
子类增加自己的方法,并调用父类的方法

甚至是修改父类的方法,为己所有。

#@File :demo_lei.py
import gc
class People(object):
    color = 'yellow'
    def __init__(self, c):
        print "Init..."
        self.dwell = 'Earth'
    def think(self):
        print "This is Parent`s think"
class Chinese(People):
    def __init__(self):
        # People.__init__(self, 'red')
        super(Chinese, self).__init__('red')
    def talk(self):
        print "I like talking"
    def think(self):
        print "child`s think"
cn = Chinese()
cn.talk()
cn.think()

Init...
I like talking
child`s think
修改父类中的方法,为己所用

多重继承:

python支持多重继承,即一个类可以继承多个父类:语法 class childnam(parent_1,Parent_2,...)

#@File :demo_lei.py
class People(object):
    color = 'yellow'
    def __init__(self):
        print "Init..."
        self.dwell = 'Earth'
    def think(self):
        print "I am a %s" % self.color
        print "My home is %s" % self.dwell
class Martian(object):
    color = 'red'
    def __init__(self):
        self.dwell = 'Martian'
# class Chinese(People, Martian):
class Chinese(Martian, People):
    def __init__(self):
        super(Chinese, self).__init__()
        # People.__init__(self)
cn = Chinese()
cn.think()

I am a red
My home is Martian
多重继承

其中要注意,子类继承父类的__init__方法时,尤其是多重继承需要修改前后位置的情况,如果没有super一定要记得修改父类的名称。实验过程中,就因为忘记而出现问题,得到的结果不正确的情况。所以这种情况,推荐super。

需要注意到是:当父类中出现多个自定义的__init__方法时,多重继承只执行第一个类的__init__方法,其他不执行。但是注意下面这个例子:

#@File :demo_lei.py
class People(object):
    color = 'yellow'
    def __init__(self):
        print "Init..."
        self.dwell = 'Earth'
        self.color = 'yellow'
    def think(self):
        print "I am a %s" % self.color
        print "My home is %s" % self.dwell
class Martian(object):
    color = 'red'
    def __init__(self):
        self.dwell = 'Martian'
# class Chinese(People, Martian):
class Chinese(Martian, People):
    def __init__(self):
        # super(Chinese, self).__init__()
        People.__init__(self)
cn = Chinese()
cn.think()

Init...
I am a yellow
My home is Earth
指定继承的__init__

总结:

类的属性-总结:

var5 = '全局变量 var5'
class MyClass(object):
    var1 = '类属性,类的共有属性 var1'
    __var2 = '类的私有属性 __val2'
    def func1(self):
        self.var3 = '对象的公有属性 var3'
        self.__var4 = '对象的私有属性 __var4'
        var5 = '函数的局部变量 var5'
        print self.__var4
        print var5
        # var6 = print '__var2'
    def func2(self):
        print self.var1
        print self.__var2
        print self.var3
        print self.__var4
        print var5
mc = MyClass()
print mc.var1
print mc._MyClass__var2
mc.func1()
print mc.var3
print('#####################    私有属性测试     ############')
mc.func2()
print('####    类的内置属性测试,分别通过对象和类调用     ############')
print mc.__dict__
print MyClass.__dict__

类属性,类的共有属性 var1
类的私有属性 __val2
对象的私有属性 __var4
函数的局部变量 var5
对象的公有属性 var3
#####################    私有属性测试     ############
类属性,类的共有属性 var1
类的私有属性 __val2
对象的公有属性 var3
对象的私有属性 __var4
全局变量 var5
####    类的内置属性测试,分别通过对象和类调用     ############
{'_MyClass__var4': 'xe5xafxb9xe8xb1xa1xe7x9ax84xe7xa7x81xe6x9cx89xe5xb1x9exe6x80xa7 __var4', 'var3': 'xe5xafxb9xe8xb1xa1xe7x9ax84xe5x85xacxe6x9cx89xe5xb1x9exe6x80xa7 var3'}
{'func2': <function func2 at 0x032778F0>, '__module__': '__main__', 'var1': 'xe7xb1xbbxe5xb1x9exe6x80xa7xefxbcx8cxe7xb1xbbxe7x9ax84xe5x85xb1xe6x9cx89xe5xb1x9exe6x80xa7 var1', '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, 'func1': <function func1 at 0x03277970>, '__dict__': <attribute '__dict__' of 'MyClass' objects>, '_MyClass__var2': 'xe7xb1xbbxe7x9ax84xe7xa7x81xe6x9cx89xe5xb1x9exe6x80xa7 __val2', '__doc__': None}
类的属性总结

类的方法-总结:

#@File :demo_lei_fangfa.py
class MyClass(object):
    name = 'Test'

    def func1(self):
        print self.name,    #这里结尾没有','则会分行显示!
        print "我是公有方法"
        self.__func2()
    def __func2(self):
        print self.name,
        print "我是私有方法"
    @classmethod            #装饰器表示这个方法可以被类调用
    def classFun(self):
        print self.name,
        print "我是类方法"
    @staticmethod
    def staticFun():        #静态方法与动态方法不同,定义时不需要使用self
        print MyClass.name,
        print "我是静态方法"
mc = MyClass()
mc.func1()
MyClass.classFun()
MyClass.staticFun()

Test 我是公有方法
Test 我是私有方法
Test 我是类方法
Test 我是静态方法
类的公有方法与类的私有方法

类的内置方法:

#@File :demo_lei_fangfa.py
class MyClass(object):
    name = 'Test'
    def __init__(self):     #初始化程序。
        self.func1()
        self.__func2()
        self.classFun()
        self.staticFun()
    def func1(self):
        print self.name,    #这里结尾没有','则会分行显示!
        print "我是公有方法"
        # self.__func2()
    def __func2(self):
        print self.name,
        print "我是私有方法"
    @classmethod            #装饰器表示这个方法可以被类调用
    def classFun(self):
        print self.name,
        print "我是类方法"
    @staticmethod
    def staticFun():        #静态方法与动态方法不同,定义时不需要使用self
        print MyClass.name,
        print "我是静态方法"
mc = MyClass()              #这里可以算是类的实例化,由于__init__是初始化,所以程序执行时就将__init__下面的程序都执行了。


Test 我是公有方法
Test 我是私有方法
Test 我是类方法
Test 我是静态方法
关于类的私有属性
人不努力的时候,老天是会一点点把你的天赋收走的。
原文地址:https://www.cnblogs.com/shiyan1sheng/p/7844515.html