Python 面向对象

Python 面向对象

简介

编程有俩种编程方式:

  1. 面向过程
  2. 面向对象

创建对象

在python中使用 class关键字声明对象 注意命名方式 一般使用大驼峰命名法

class Student(object):
#class Student: 第二种声明方式
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def sayhello(self):
        print('Hello Object')

if __name__ == '__main__':
    s1 = Student('zzy',20)
    print(s1.name)
    print(s1.age)
    s1.sayhello()

对象中的魔法方法:

对象中的魔法方法 是自动调用的

  1. __ init__ 对象创建时调用
  2. __ del __ 对象销毁时调用
  3. __ call __ 可以让对象变成可以调用的函数
  4. __ repr __ 重写输出的对象的格式
  5. __ str __ 重写输出的对象的格式
  6. __ eq __ 对比表面值是否相等
  7. __ slots __ 设置属性是否可以在外部调用和添加
class Student(object):
#class Student:
    __slots__ = ('name','age') # 对象中的对象是否可以让外部调用  可以调用的属性或者方法放入其中 如果没有在其中声明外部不可以给对象添加属性 和 方法


    def __init__(self,name,age): # 对象创建的时候调用
        self.name=name
        self.age=age

    def __del__(self):  # 对象销毁的时候调用
        print('对象已经删除')

    def __call__(self, *args, **kwargs): # 可以让对象变成一个可调用的函数   外部可以直接使用s1() 调用对象中的__call__方法
         pass

    def __repr__(self): # 对象在输出的时候会输出 对象类型 和 对象的内存地址  重写这个 或者 str 方法 可以改变输出的内容
        pass

    def __str__(self): # repr 方法 注重的是   str 方法 注重的是 显示 一般使用str
        pass

    def __eq__(self, other): # == 在外部使用==号使用的就是对象中的eq方法  对象的比较使用 is 关键字  is对比的是内存地址  eq重写对比的是表面值
          return  self.name==other.name and self.age==other.age


    def __gt__(self, other): # >
        pass

    def __ge__(self, other): # >=
        pass

    def __ne__(self, other): # !=
        pass

    def __lt__(self, other): # <
        pass

    def __le__(self, other): # <=
        pass

    def __int__(self): # int()
        pass
        
    def sayhello(self):
        print('Hello Object')

if __name__ == '__main__':
    s1 = Student('zzy',20)
    s2 = Student('zzy',20)
    print(s1 is s2)  # flase is对比的是内存地址
    print(s1 == s2)  # true == 调用的是对象中的 __eq__方法
    print(s1.name)
    print(s1.age)
    s1.sayhello()

内置属性

class Student(object):
    # __slots__ = ('name','age') # 对象中的对象是否可以让外部调用  可以调用的属性或者方法放入其中 如果没有在其中声明外部不可以给对象添加属性 和 方法

    def __init__(self,name,age): # 对象创建的时候调用
        self.name=name
        self.age=age

    def hello(self):
        print('hello python')

if __name__ == '__main__':
    s1 = Student('zzy',20)

    dir(s1)
    print(s1.__class__) # <class '__main__.Student'>  模块名
    print(s1.__dict__) # {'name': 'zzy', 'age': 20}把对象转化为字典
    print(s1.__doc__) # 输出类的描述对象
    print(s1.__module__) # 模块名
    # print(s1.__slots__)

把对象当作字典使用

  1. setitem(self, key, value)
  2. getitem(self, item):
class Student(object):
    # __slots__ = ('name','age') # 对象中的对象是否可以让外部调用  可以调用的属性或者方法放入其中 如果没有在其中声明外部不可以给对象添加属性 和 方法

    def __init__(self,name,age): # 对象创建的时候调用
        self.name=name
        self.age=age

    def __setitem__(self, key, value): # 当使用操作字典的 方式来设置对象属性时 会自动调用 setitem方法
        self.__dict__[key]=value

    def __getitem__(self, item): # 当使用操作字典的 方式来获取对象属性时 会自动调用 setitem方法
        return self.__dict__[item]
    def __str__(self):
        return "name:{},age:{}".format(self.name,self.age)

    def hello(self):
        print('hello python')

if __name__ == '__main__':
    s1 = Student('zzy',20)
    print(s1['name'])
    s1['age']=22
    print(s1)

类属性和对象属性

class Student(object):
    # __slots__ = ('name','age') # 对象中的对象是否可以让外部调用  可以调用的属性或者方法放入其中 如果没有在其中声明外部不可以给对象添加属性 和 方法
    type='学生'
    def __init__(self,name,age): # 对象创建的时候调用
        self.name=name
        self.age=age

    def hello(self):
        print('hello python')

if __name__ == '__main__':
    s1 = Student('zzy',20)
    s2 = Student('zjw',22)
    print(Student.type) #学生
    s1.type='hhh' # 注意 这里无法修改 类属性  只是在自己的内存中创建了一个新的属性
    print(s1.type) #  hhh
    print(s2.type) #  学生
    print(Student.type)  #  学生
    Student.type='xxx'
    print(Student.type) # xxx 修改类属性
    print(s2.type) # xxx  s2没有type属性 所以使用的是 Student的类属性
    print(s1.type) # hhh  s1 拥有自己type属性 所以用自己的

私有方法 和 私有属性

以 __ 双下划线开头 表示 是 私有的属性 在外部不能直接获取

获取私有属性的方法

class Student(object):
    def __init__(self,name,age,__money): # 对象创建的时候调用
        self.name=name
        self.age=age
        self.__money=__money
    def hello(self):
        print('hello python')
    def get_money(self):
        return self.__money
    def set_money(self,v):
        self.__money=v

if __name__ == '__main__':
    s1 = Student('zzy',20,300)
    # print(s1.__money)   私有变量 无法获取
    # 获取方式 1
    print(s1._Student__money) # 私有方法同理
    
    # 2 定义get set 方法获取
    print(s1.get_money())
    s1.set_money(20)
    print(s1.get_money())

类方法和静态方法

class Student(object):
    type='zzy'
    def __init__(self, name, age):  # 对象创建的时候调用
        self.name = name
        self.age = age
    @staticmethod # 当你不需要对象的属性是可以使用static方法  类 或 对象 都可以调用
    def hello():
        print('hello python')
    @classmethod # 类方法 如果一个函数只用到类属性 那么这个函数 可以定义为类方法  cls==Student true
    def demo(cls):
        print(cls.type) # 类方法可以调用本类中的属性 而静态方法不行
        print('yes')

    def eat(self):
        print('eat')



if __name__ == '__main__':
    s1 = Student('zzy', 20)
    s1.eat() # eat
    Student.eat(s1) # eat
    
    Student.hello() # hello python
    s1.hello() # hello python
    
    Student.demo() # zzy yes
    s1.demo() # zzy yes
    
    # 总结 静态方法 无论是对象 还是 实列 都可以调用
    ##    类方法 无论是对象 还是 实列 都可以调用 但是 类方法可以使用类属性
    #      实列方法 无论是对象还是 实列 都可以调用 但是类调用时 需要自己传参 而 实列对象 不需要



单例设计模式

简介 : 在一个范围内 只允许一个实列对象 把地址执行同一个地址

class Student(object):
    __instance=None
    __first = True
    def __new__(cls, *args, **kwargs):
        if cls.__instance is None:
            cls.__instance = object.__new__(cls) # 改变对象的执行地址
        return cls.__instance
    def __init__(self, name, age):  # 对象创建的时候调用
        if self.__first: 
            self.name = name
            self.age = age
            self.__first=False # 只修改一次 后面无法修改

    def eat(self):
        print('eat')



if __name__ == '__main__':
    s1 = Student('zzy', 20)
    s2 = Student('zjy', 20)
    print(s1 is s2) #True
    print(s2.name,s2.age) # zzy 20




面向对象的三大特性 封装 继承 和 多态

封装

函数是对语句的封装 类是对函数和变量的封装

继承

类和类之间可以手动的建立父子关系 父类的属性和方法 子类可以使用

python 支持多继承

class Animal:
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def sleep(self):
        print(self.name,'sleep')


class Dog(Animal): # 括号中就是继承的父类
    # def __init__(self, name, age):
    #     self.name = name
    #     self.age = age
    #
    # def sleep(self):
    #     print(self.name, 'sleep')

    def ww(self):
        print(self.name,'waowao')


class Student(Animal):
    # def __init__(self, name, age):
    #     self.name = name
    #     self.age = age
    #
    # def sleep(self):
    #     print(self.name, 'sleep')

    def study(self):
        print(self.name, 'study')

if __name__ == '__main__':
    d1 = Dog('旺财',5)
    print(d1.name) # 在父类中声明的属性和方法 子类可以直接使用 注意 在类中没有重写 __ init __方法的话 会自动的去自己的父类去找 找到使用父类的方法 没找到去object类的__init__方法 
    print(d1.age)
    d1.sleep()
    d1.ww()

继承顺序 和 深度优先

使用 __ mro __ 属性查看调用顺序

class Animal:
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def sleep(self):
        print(self.name,'sleep')

class People:
    def __init__(self,height):
        self.height=height

    def run(self):
        print('run')


class Student(Animal,People):

    def study(self):
        print(self.name, 'study')

if __name__ == '__main__':
    s1=Student('zzy',2)  # 如果 有相同的方法 那么继承的是前面的那个类的 方法 先到先得  深度优先  如 __inti__ 方法 使用的是Animal 的方法
    print(Student.__mro__) # (<class '__main__.Student'>, <class '__main__.Animal'>, <class '__main__.People'>, <class         # #'object'>) 调用的顺序
    s1.sleep()
    s1.run()
    s1.study()

私有属性 和 私有方法的不能被继承

class Animal:
    def __init__(self,name,age,money):
        self.name=name
        self.age=age
        self.__money = money

    def sleep(self):
        print(self.name,'sleep')

    def __hh(self):
        print('不能调用')

class Student(Animal):

    def study(self):
        print(self.name, 'study')

    def __hq(self):
        print('hql')

if __name__ == '__main__':
    s1=Student('zzy',2,1000) 
    print(s1.name) # 可以
    print(s1.age) # 可以
    s1.study() #可以
    s1._Student__hq() # 自己类中定义的私有方法可以调用
    # print(s1._Animal__money)     1000         # 继承的私有方法和属性都是无法调用 的 私有属性不继承  但是 可以通过 父类直接调用
    # s1._Animal__hh() 输出  不能调用

子类重写父类方法

super 关键字

class Animal:
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def sleep(self):
        print('Animal sleep')


class Student(Animal):
    def __init__(self,name,age,height):
        super(Student, self).__init__(name,age) # super  当继承的方法不再满足子类的需求时 可以使用super 调用父类的方法
        self.height = height

    def __str__(self):
        return 'name:{} age:{} height:{}'.format(self.name,self.age,self.height)
    def study(self):
        print(self.name, 'study')

    def sleep(self):
        print('Student sleep')

if __name__ == '__main__':
    s1=Student('zzy',20,180)  # 如果 有相同的方法 那么继承的是前面的那个类的 方法 先到先得  深度优先
    s1.sleep() # Student sleep 调用自己的方法
    print(s1) # name:zzy age:20 height:180

多态

多态是基于继承 通过子类重写父类的方法

达到不同的子类对象调用相同的父类方法 得到不同的结果

作业 提高代码的灵活度

class Dog(object):
    def work(self):
        print("狗在工作")

class OneDog(Dog):
    def work(self):
        print('OneDog在工作')

class TwoDog(Dog):
    def work(self):
        print('TwoDog 在工作')

class People(object):
    def __init__(self,name,dog):
        self.name = name
        self.dog = dog
    def people_dog(self):
        self.dog.work()

if __name__ == '__main__':
    one_dog = OneDog()
    two_dog = TwoDog()

    p = People('zzy',one_dog)
    p.dog.work() # 输入不同的狗 会执行不同的狗的办法  增加的代码的灵活性

    p2 = People('zzy',two_dog)
    p2.dog.work()

有关对象的相关方法

  1. is 身份运算符 是用来比较两个对象 是否是同一个对象 比较的是地址
  2. isinstance 用来判断一个对象是否是由指定的类 (或者父类)实列化出来的 isinstanc(p1,Student)
  3. issubclass 用来判断一个类是否是另一个类的子类
posted @ 2021-08-19 15:43  zhiy  阅读(24)  评论(0)    收藏  举报