Python研究学习--8--面向对象

版权声明:本文为博主原创文章,转载本站文章请注明作者和出处,请勿用于任何商业用途。 https://blog.csdn.net/wutianxu123/article/details/82503869

8.1 面向对象

python将所有事物都看作是对象
面向对象的三大特性:封装、继承、多态。

类和对象:
类: 相同事物的组成。如汽车类、房子类。它具有属性和方法
类变量: 类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。
方法重写: 如果从父类继承的方法不能满足子类的需求,可以对其进行改写。
实例变量: 定义在类里面函数中的变量,只作用于当前实例的类。
继承: 原本的类叫基类,继承原本类的这个类叫派生类。
实例化: 创建一个类的实例,类的具体对象。
方法: 类中定义的函数。
对象: 具体的目标事物。如具体的某一辆车。它符合该类的属性和方法,是对象的实例

`类和对象的关系:
某类的某个对象调用某种方法实现目标任务 #例如:人类叫张三的说一句话

8.2 类和对象

定义类:
使用class关键字定义一个类,且类名的首字母要大写
主要目的: 所表达的信息复杂,无法用简单变量实现时,就需要用类表示
类把需要的变量和函数组合在一起。这种包含也称为“封装”

定义类的实现方式:

class 类名:
    “类的帮助信息”                 #可以使用:“类名.__doc__”查看
    成员变量
    成员函数(至少有一个形参)         #形参可以不需要传值。因为接收的是这个类本身

定义对象:
创建对象的过程称之为实例化。因为类是模糊的描述。
#以人类和张三为例

对象包含三方面特性:句柄、属性、方法

句柄用于区分不同对象               #对象名就是句柄
属性要和类中的成员变量对应          #类中的变量就是属性
方法要和类中的成员函数对应          #类中的函数就是方法

定义对象的实现方式:

对象名 = 类名()                  #实例化类
对象名.属性/方法名                #方法名必须是类中定义过的。可以是变量、函数等等

操作类属性:方法-指类中的函数,属性-指类中的变量

getattr(类名,属性名)             #访问对象的属性。
hasattr(类名,属性名)             #检查是否存在一个属性。
setattr(类名,属性名,值)          #设置一个属性。如果属性不存在,会创建一个新属性。
delattr(类名,属性名)             #删除属性。

对象销毁-垃圾回收:
使用计数来跟踪和回收。在python内部记录着对象的引用次数,当对象不再需要时(即引用次数为0),在某个恰当的时刻,解释器会回收占用的内存空间。

`语法:

__del__ :  析构函数。该函数在对象销毁时被调用。

代码实例:

#coding=utf-8

class test(object):                     #所有的class都是object的派生类
    a = 1                               #此处a是test类的属性
    def func_1(self):                   #此处func_1是test类的方法(函数)
        return self.arg1,self.arg2      #下方已转化为全局变量,此处虽不是同一函数下但可以调用

    def __init__(self,arg1,arg2):       #此处添加几个参数,实例化时就引入几个具体数
#构造函数。init函数主要是用来接收实例化时传入的初始值,之后再对其值进行处理,例如转化为全局值,使之可以被类内的其它函数所使用
        self.arg1 = arg1                #通过self将其转化为class内部的全局变量
        self.arg2 = arg2

    def __del__(self):                  #析构函数。主要是起销毁作用
        del self.arg1                   #删除掉全局变量。一般不需要操作,python会将其自动销毁
        del self.arg2

t = test(1,4)                           #先实例化类,之后才能将类中的函数及变量拿到外部去使用。注意实例化并传值,该值首先传给init函数
print t.a                               #在类外面使用内部变量。注意点号。输出:1
print t.func_1()                        #在类外面使用内部函数。输出:(1,4)

代码实例:

# -*- coding:utf-8 -*-
a=[1,2,3,4,5,6]

#定义类。object是所有类之母,如果该类没有继承任何父类,则object将作为默认的父类。
class ceshi(object): 
    def name(self,a=None):           
#函数中至少有一个形参。注意self是默认参数,在类里面定义函数第一个参数必须是self。
#self代表了这个对象本身。即这个类。             
#self在该类内部是可以被全局调用的。

        return self.var1               #已被self声明为类内全局变量
    def __init__(self,var1):           #init接收实例化时传入的初始值
        self.var1=var1                 #将传入的初始值声明为类内全局变量

#类的实例化
s=ceshi(u"这是一个测试字符串")
print s.name(a)                        #调用ceshi类的内置函数。先实例化再传参

#对比外置函数的使用
def ceshi2(s):
    return s
t=ceshi2(a)
print t
print ceshi2(a)                        #也可以直接输出

代码实例:

# -*- coding: UTF-8 -*-

class Lei:                              #定义类。注意类名首字母大写
    u'所有员工的基类'                     #类的帮助文档
    empCount = 0                        #定义类内的变量
    hs=123

    def __init__(self, name, salary):   #定义类内的初始__init__函数,用于接收传参
        self.name = name                #将函数参数转换为类内全局变量
        self.salary = salary
        Lei.empCount += 1

    def displayCount(self):
        print "Total Lei %d" % Lei.empCount

def displayLei(self):
print "Name : ", self.name,  ", Salary: ", self.salary

emp1 = Lei("Zara", 2000)                #创建 Lei 类的第一个对象。即实例化
emp2 = Lei("Manni", 5000)               #创建 Lei 类的第二个对象。
emp1.displayCount()                     #间接调用类内函数displayCount
emp2.displayLei()                       #间接调用类内函数displayLei
print "Total Lei %d" % Lei.empCount     #输出类中的变量
print Lei.__doc__                       #查看类的帮助文档

print hasattr(Lei, 'hs')                #如果存在 'hs' 属性返回 True。
print getattr(Lei, 'hs')                #返回 'hs' 属性的值
print setattr(Lei, 'hs', 8)             #添加属性 'hs' 值为 8
print delattr(Lei, 'hs')                #删除属性 'hs'

8.3 内置类属性

内置类:注意是前后双下划线

__dict__          #查看该类的属性(变量),这些属性以字典形式输出。 
__doc__           #主要用来查看类的帮助文档
__name__          #如果是对应模块就显示模块名字,如果是对应类就显示类的名字
__module__        #查看该类/函数是在哪个模块下定义的,然后返回该模块的名称。 
__bases__         #查看该类的父类,这些父类以元组形式输出。

代码实例:

# -*- coding: UTF-8 -*-

class Yuangong:                                        #无继承普通类
    '所有员工的基类'                                     #类的帮助文档
    empCount = 0

    def __init__(self, name, salary):                  #初始化函数__init__
        pass                

print "Yuangong.__doc__:", Yuangong.__doc__            #帮助文档
print "Yuangong.__name__:", Yuangong.__name__          #类名
print "Yuangong.__module__:", Yuangong.__module__      #模块名:__main__
print "Yuangong.__bases__:", Yuangong.__bases__        #父类。此处为空
print "Yuangong.__dict__:", Yuangong.__dict__          #类属性
------------------------------------------------------------------------------------
类属性返回结果:
Yuangong.__dict__: {'__module__': '__main__', 'empCount': 0, '__doc__': u'所有员工的基类', '__init__': <function __init__ at 0x0000000002DF2C18>}

8.4 继承

主要用来实现代码重用,继承了某个类就相当于又写了一遍该类的代码
语法:

class 类名(基类名):            #父类类写在括号里,外面的类又叫派生类

特点:
1、在继承中基类的构造(即__init__函数)不会被自动调用,它需要在派生类中亲自调用。即:(__init__再写一遍)。
2、调用基类函数时,需要加上基类的类名前缀,且需要带上self参数变量。而调用自身函数时,不需要带上self参数
3、先在本类中查找调用的函数,找不到时再到基类中查找。

多重继承

class 类名(基类名1、基类名2、基类名3):

代码实例:

# -*- coding: UTF-8 -*-

class Parent:                                      # 定义父类
    _parentAttr = 1                                #父类属性(变量)。受保护变量
    def __init__(self):                            #如果直接执行父类,它将先行执行。此处它不执行,是因为我们只是调用了它,并没有直接执行它。
        print u"调用父类构造函数"
    def parentMethod(self):
        print u'调用父类方法'
    def _setAttr(self, attr):                      #注意是受保护方法。前缀单下划线
        Parent._parentAttr = attr                  #调用类内全局(受保护)变量,并被传入新值
    def getAttr(self):
        print u"父类属性 :", Parent._parentAttr     #输出传入的新值(受保护)

class Child(Parent):                               #定义子类,该子类继承父类
    def __init__(self):                            #构造函数,先行执行(虽然在该函数中没有任何作用)。先行执行是因为我们直接执行的是这个类。而每个类中都应该定义自己的init函数,而不是去继承。
        print u"调用子类构造方法"
    def childMethod(self):                         #子类中的子函数
        print u'调用子类方法'

c = Child()                                        #实例化子类
c.childMethod()                                    #调用子类的方法
c.parentMethod()                                   #调用父类方法
c._setAttr(200)                                    #子类再次调用父类的(受保护)方法并设置属性值。
c.getAttr()                                        #再次调用父类的方法,获取属性值

8.5 方法重写

当父类的函数不能满足要求时,可以在子类中重写父类方法。
注意!重写后的方法只适用于该子类。其它类调用父类时还是使用父类中的方法。

代码实例:

# -*- coding: UTF-8 -*-

class Parent:                              #定义父类
    def myMethod(self):                    #定义父类中的方法
        print u'调用父类方法'

class Child(Parent):                       #定义子类,该子类继承父类
    def myMethod(self):                    #定义子类中的方法。和父类方法相同,但父类方法不能满足子类需求,因此此处重写父类方法
        print u'调用子类方法'

c = Child()                                #子类实例化
c.myMethod()                               #调用子类重写后的方法

8.6 私有化

前双下划线说明:
类的私有属性(变量)
#私有属性不能被外部函数访问,也不能被继承

__变量名                 #前面以两个下划线开头即可
self.__变量名            #调用私有变量

类的私有方法(函数) #私有方法不能被外部访问,也不能被继承

__函数名                 #前面以两个下划线开头即可
self.__函数名            #调用私有函数

注意:不允许实例化的类访问私有数据(外部访问)。即类外部实例化时不能对私有数据实例化。

前单下划线说明:
类的受保护属性/方法 #受保护属性可以被继承,但不能被外部访问(即父类和子类可访问)

_变量名                  #注意是单下划线
_函数名                  #调用受保护的数据。注意是单下划线

前后双下划线说明:
特例函数(方法)。如:__init__()

代码实例:

# -*- coding: UTF-8 -*-

class JustCounter:
    __secretCount = 0                  #私有变量。前缀双下划线
    publicCount = 0                    #公有变量

    def count(self):
        self.__secretCount += 1        #私有变量做运算
        self.publicCount += 1          #公有变量做运算
        print self.__secretCount       #输出私有变量。成功

counter = JustCounter()                #实例化
counter.count()                        #调用函数。输出0+1=1
counter.count()                        #再次调用函数。输出1+1=2
print counter.publicCount              #调用输出公有变量。此时为2
print counter.__secretCount            #调用输出私有变量。报错!外部不能访问私有变量
print counter._JustCounter__secretCount       #外部可访问私有属性方法了。用法在此:实例化名._类名__私有变量名       
                                              #注意下划线数量

猜你喜欢

转载自blog.csdn.net/wutianxu123/article/details/82503869