Python(6)

面向对象三大特性

  • 封装:根据职责将属性和方法封装到一个抽象的类中
  • 继承:实现代码的重用,相同的代码不需要重复编写
  • 多态:不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活度

dir内置函数

方法名 :python提供的内置函数和属性
可以使用:

dir([])   #查看列表的内置函数和属性

定义类

只包含方法

class 类名:
    def 方法1(self,参数列表):
        pass
    def 方法2(self,参数列表):
        pass

方法的定义格式与函数基本一样,区别在于方法的第一个参数必须是self,并且类名的命名方式必须是大驼峰命名法

self参数

哪个对象调用该方法,self就指该对象:

class Cat:
    def eat(self):
        print("%s eat fish" %self.name)
tom = Cat()
tom.name = "Tom"   #为tom增加name属性(不推荐)
tom.eat()      #输出Tom eat fish
bob = Cat
bob.name ="Bob"
bob.eat()    #输出Bob eat fish

初始化方法

  1. 当使用类名创建对象时,会自动执行以下操作:
  • 为对象在内存中分配空间:创建对象
  • 为对象的属性设置初始值:初始化方法(init)
  1. 这个初始化方法就是init方法,init 是对象的内置方法,init 方法是专门用来定义一个类具有哪些属性的方法
    class Cat:
     def __init__(self):
         print("这是一个初始化方法")
    # 使用类名()创建对象时,会自动调用初始化方法__init__
    tom = Cat()   #输出结果 这是一个初始化方法

在初始化方法内部定义属性

init方法内部使用self.属性名=属性的初始值 就可以定义属性。在定义属性后,再使用该类创建对象,都会拥有该属性

class Cat:
    def __init__(self):
        self.name="Hello"
tom = Cat()
bob = Cat()
print(tom.name)
print(bob.name)
# 输出结果
Hello
Hello

改造初始化方法

class Cat:
    def __init__(self,name):
        self.name=name
tom = Cat("Tom")
bob = Cat("Bob")
print(tom.name)   #输出Tom
print(bob.name)   #输出Bob

内置方法和属性

del 方法

  1. 当一个对象被从内存中销毁时,自动调用del方法
  2. 如果希望对象在被销毁前再做一些事情,可以考虑del 方法
  3. 生命周期:
  • 一个对象从调用类名()创建,生命周期开始
  • 一个对象del对象一旦被调用,生命周期结束
  • 在对象的生命周期内,可以访问对象属性,或者让对象调用方法
在代码执行结束后回收

tom是全局变量,del 函数会在所有代码执行完毕后自动调用

class Cat:
    def __init__(self,name):
        self.name=name
    def __del__(self):
        print("%s 已销毁"%self.name)
tom = Cat("Tom")
print("----------------------")
# 输出结果
----------------------
Tom已销毁
使用del方法删除对象
class Cat:
    def __init__(self,name):
        self.name=name
    def __del__(self):
        print("%s 已销毁"%self.name)
tom = Cat("Tom")
del tom
print("----------------------")
# 输出结果
Tom已销毁
----------------------

str 方法

返回对象的描述信息,print函数输出使用,必须返回一个字符串

class Cat:
    def __init__(self,name):
        self.name=name
    def __del__(self):
        print("%s 已销毁"%self.name)
tom = Cat("Tom")
print(tom)
#输出结果
<__main__.Cat object at 0x000002D897863B88>
Tom 已销毁

使用str方法后:

class Cat:
    def __init__(self,name):
        self.name=name
    def __del__(self):
        print("%s 已销毁"%self.name)
    def __str__(self):
        return "hello world"
tom = Cat("Tom")
print(tom)
# 输出结果
hello world
Tom 已销毁

需求分析

  1. 画类图
  2. 被使用的类应该先开发
  3. 类与类之间调用是通过对象实现的

身份运算符

身份运算符被用于比较两个对象的内存地址是否一致(是否是对同一个对象的引用)。在Python中对None比较时,建议使用is判断

  • is: is是判断两个标识符是不是引用同一个对象。 x is y 类似id(x)==id(y)
  • is not: is not是判断两个标识符是不是引用不同对象。 x is not y 类似id(x)!=id(y)

注:id()是查看变量的内存地址

is和==的区别

  • is用于判断两个对象引用对象是否是同一个(比较地址)
  • ==用于判断引用对象的值是否相等

私有属性和私有方法

私有属性和私有方法只能在对象的内部被访问,不能在外部进行访问

  • 私有属性:对象不希望公开的属性
  • 私有方法:对象不希望公开的方法
    定义方法,在属性名或方法名前加两个下划线

私有属性

class Woman:
    def __init__(self,name):
        self.name = name
        self.__age = 18
    def secret(self):
        print("%s的年龄为%d" % (self.name,self.__age))   #true,在对象内部的方法可以访问私有属性

xiaofang = Woman("小芳")
print(xiaofang.__age) # false,在对象外部不能访问私有属性
xiaofang.secret()

私有方法

class Woman:
    def __init__(self,name):
        self.name = name
        self.__age = 18
    def __secret(self):
        print("%s的年龄为%d" % (self.name,self.__age))

xiaofang = Woman("小芳")
xiaofang.__secret() #error,在对象外部不能访问私有方法

伪私有属性和私有方法

Python中,并没有真正意义上的私有。在给属性、方法命名时,实际上是对名称做了一些特殊处理,使得外界无法访问。
可以使用以下方式访问私有属性和方法(在开发中不要使用这种方法访问私有属性和私有方法)

class Woman:
    def __init__(self,name):
        self.name = name
        self.__age = 18
    def __secret(self):
        print("%s的年龄为%d" % (self.name,self.__age))

xiaofang = Woman("小芳")
print(xiaofang._Woman__age)
xiaofang._Woman__secret() 

继承

继承语法:

class 类名(父类名):
     pass

继承的传递性

如果B类继承A类,C类继承B类,则C类也继承自A类。子类可以访问父类的公共属性和方法。

重用

在子类中重写父类的同名方法,使用子类对象调用方法时,会调用子类中重写的方法。

覆盖

子类方法完全不同于父类的同名方法

class Dog:
    def bark(self):
        print("汪汪汪")

class Xiaotianquan(Dog):
    def bark(self):
        print("可以说话")

xiaotian = Xiaotianquan()
xiaotian.bark()    
#输出结果 : 可以说话

扩展

子类方法在父类同名方法的基础上再加上额外的属性。使用super().创建一个新的对象调用父类中封装的方法

class Dog(Animal):
    def bark(self):
        print("汪汪汪")

class Xiaotianquan(Dog):
    def bark(self):
        #1.针对子类的特殊需求,编写代码
        print("可以说话")
        #2. 使用super().调用原本在父类中封装的方法
        super().bark()
        #3. 增加其他子类的方法
        print("asdsadddd")

xiaotian = Xiaotianquan()
xiaotian.bark()
# 输出结果
可以说话
汪汪汪
asdsadddd

多继承

一个子类可以继承多个父类,并且拥有所有父类的属性和方法:

class 类名(父类名1,父类名2....):
    pass

如果在多个父类中具有同名的方法或属性,应避免使用多继承。

MRO方法顺序

在多继承中可以使用类的内置属性mro查看方法的调用顺序

class A:
    pass
class B:
    pass
class C:
    pass
class D(C,B,A):
    pass

print(D.__mro__)
#输出结果 
(<class '__main__.D'>, <class '__main__.C'>, <class '__main__.B'>, <class '__main__.A'>, <class 'object'>)  #结果中显示的顺序即对方法和属性查找的顺序

注:Object类是所有类的基类

多态

不同的子类对象调用相同的父类方法,产生不同的执行结果

class Dog:
    def __init__(self,name):
        self.name = name
    def game(self):
        print("%s正在玩耍" %(self.name))

class Xiaotianquan(Dog):
    def game(self):
        print("%s正在巡查公务" % (self.name))

class Person:
    def __init__(self,personName):
        self.personName = personName
    def playWith(self,dog):
        print("%s与%s正在玩耍" % (self.personName,dog.name))
        dog.game() #传递不同的对象产生不同的结果

person = Person("小明")
dog = Dog("旺财")
person.playWith(dog)  
#输出结果
小明与旺财正在玩耍
旺财正在玩耍

xiao = Xiaotianquan("哮天犬")
person.playWith(xiao)
#输出结果
小明与哮天犬正在玩耍
哮天犬正在巡查公务

类对象

在Python中,类也是一个对象,由类创建的对象叫做实例对象

类属性

类属性就是给类对象定义的属性,通常用来记录这个类相关的特征

一个工具类,需要统计所有该类创建的实例对象的数量

class Tool(object):
    count = 0
    def __init__(self,name):
        self.name = name
        # 让类属性加1
        Tool.count+=1

tool1 = Tool("斧头")
tool2 = Tool("铲子")
print(Tool.count)  # 输出结果 :2

类方法

针对类对象定义的方法,语法如下:

@classmethod   #告诉解释器这是一个类方法
def 类方法名(cls): #第一个参数必须是cls
    pass

实例:使用一个类方法打印输出创建的工具个数

class Tool(object):
    count = 0
    def __init__(self,name):
        self.name = name
        # 让类属性加1
        Tool.count+=1
    @classmethod
    def showToolCount(cls):
        print("已经创立了%d个工具" % (cls.count))

tool1 = Tool("斧头")
tool2 = Tool("铲子")
#类方法只能通过类名调用,cls不需要传递,解释器会自动传递
Tool.showToolCount()  #输出结果:已经创立了2个工具

静态方法

如果一个方法同时满足以下两个条件:

  • 不需要访问实例属性或调用实例方法
  • 不需要访问类属性或调用类方法
    那么该方法可以封装成一个静态方法,语法如下:
    @staticmethod
    def 静态方法名():
      pass
    调用方式与类方法调用方法相同,都不需要创建对象

方法分类:

  • 实例方法:在方法内部需要访问实例属性(实例方法内部可以使用类名访问类属性)
  • 类方法:方法内部只需要访问类属性
  • 静态方法:方法内部,不需要访问实例属性和类属性

   转载规则


《Python(6)》 fightingtree 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录