Python 面向对象

面向对象

  1. 类和对象:

    • 定义 类 :具有某些属性和方法的对象全体称为一个类

      • class <类名>: ** #类名遵守大驼峰命名法**

      • class <类名>(object):

      • 使用**__inin__函数定义类具有的特征,这写特征称为属性**

      • 通过一个个函数取定义这个类的行为,称为方法

      • 用类创建一个新的对象的过程:

        • 首先调用**__new__方法申请一段内存地址**;
        • 接着调用**_init_传入参数,并让self指向该内存空间.并填充数据**;
        • 让s1也指向那段内存地址
      • 谁调用方法,就针对谁进行操作

        #小明今年18,身高1.78m,喜欢跑步,正在吃饭
        #小美几年17,身高1.65m,不喜欢跑步,正在吃饭
        class Student:
            #使用__inin__将类定义类具有的特征,这写特征称为属性
            def __init__(self,x,y,z):
                self.name=x
                self.age=y
                self.height=z
             #通过一个个函数取定义这个类的行为,称为方法
            def run(self):
                print('喜欢跑步')
        
            def eat(self):
                print('正在吃饭')
        
            def say_hello(self):
                print('大家好,我是',self.name)
        
        #利用类创建两个具体的对象:他们都具有name,age,height属性,也都具有run和eat方法
        s1=Student('小明',18,1.78)
        #1.首先调用__new__方法申请一段内存地址;
        #2.接着调用__init__传入参数,并让self指向该内存空间.并填充数据;
        #3.让s1也指向那段内存地址
        s2=Student('小美',17,1.65)
        print('s1的地址是ox%X'%id(s1))
        print('s1的名字是{}'.format(s1.name))
        
        #谁调用方法,就针对谁进行操作
        s1.run()
        s1.eat()
        s1.say_hello()
        s2.eat()
        #result
        s1的地址是ox1E6E448
        s1的名字是小明
        喜欢跑步
        正在吃饭
        大家好,我是 小明
        正在吃饭
        
        
    • **_slots_**方法

      • 在python中,类的属性是一种动态属性,就是可以修改和添加通过赋值语句实现

      • 使用**_slots_**方法可以使得类的属性无法添加

      • **_slots_**直接定义在类里,是一个元组,用来规定类可以存在的属性

        #s1.city  会直接报错,因为在__init__里面,并没有定义city这个属性
        #可以通过赋值语句,给对象添加或者修改属性
        s1.city='上海'   #如果没有该属性那么就添加,如果有就修改
        print(s1.city)#result
        上海
        
        class Student:
            __slots__ = ('name','age','height')  
            def __init__(self,x,y,z):
                self.name=x
                self.age=y
                self.height=z
        s=Student('小明',18,1.78)
        #s.city='上海'  #此时会报错
        
    • 魔方方法

      • 特点

        • 不需要手动调用,会在合适的时机自己调用
        • 这些方法都是以**__开始**,以**__结束**
        • 这些方法名都是系统规定好的,在合适的时机自己调用,可以手动调用
      • **_init_**方法: 创建对象时,会自动调用这个方法

      • **_del_**方法: 销毁对象时,会自动调用

      • **_str_方法和_repr_**方法:打印对象时调用,打印return的结果,优先_str_,必须是字符串

      • **_call_**方法: 可以使得对象可以像函数一样

      • 算术运算符

        • **_eq_**方法: 出现==时调用,如果不写,默认是比较内存地址
        • is 身份运算符,判断是否是同一个对象,比较的是内存地址
        • == ** 使用的时候是调用_eq_**方法,默认也是比较内存地址,除非重写
        • **_ne_方法:出现!=**时调用,如果不写默认__eq__方法取反
        • **_gt_**方法:出现 > 时调用
        • **_ge_方法:出现>=**时调用
        • **_lt_方法:出现<=**时调用
        • **_le_方法:出现<=**时调用
        • **_add_方法:出现+**时调用
        • **_sub_方法:出现-**时调用
        • **_mul_方法:出现***时调用
        • **_truediv_方法:出现/**时调用
        • **_pow_方法:出现****时调用
      • 转换运算符

        • _str_: 使用**str()**转换成字符串的时候调用
      • _int_: 使用**int()**时调用

        • _float_: 使用**float()**时调用
        class Person:
            #__init__方法:创建对象时,会自动调用这个方法
            def __init__(self,name,age,height):
                print('是__init__方法,我被调用了')
                self.name=name
                self.age=age
                self.height=height
        
            def __del__(self):   #注意程序运行结束,对象会被自动销毁
                print('我是__del__方法,我被调用了')
        
            def __str__(self):
                return '姓名{},年龄{},身高{}'.format(self.name,self.age,self.height)
            def __repr__(self):
                return 'hello world'
            
            def __call__(self, *args, **kwargs):
                return kwargs['fn'](args[0],args[1])
        
            #算术运算符
            def __eq__(self, other):
                return self.name==other.name and self.age==other.age and self.height==other.height
            def __ne__(self, other):
                return  not(self.name==other.name and self.age==other.age and self.height==other.height)
            def __gt__(self, other):
               return self.age>other.age
           def __ge__(self, other):
                return self.age>other.age
            def __lt__(self, other):
                return  self.age<other.age
            def __le__(self, other):
                return  self.age<=other.age
            def __add__(self, other):
                return self.age+other.age
            def __sub__(self, other):
                return self.age-other
            def __mul__(self, other):
                return self.name*other
            def __truediv__(self, other):
                return self.age/other
            def __pow__(self, power, modulo=None):
                return self.age**power
            #转换运算符
            __str__:使用str()转换成字符串的时候调用
            __int__:使用int()时调用
            __float__:使用float()时调用
        
        p=Person('zhangsan',18,178)
        # time.sleep(10)
        print(p)  #如果没有__str__和__repr__,会打印__name__.类名和地址
        print(p.__repr__) #自己手动调用不是特别好
        print(repr(p))  #会触发__repr__方法
        
        m=p(13,34,fn=lambda x,y: x+y)  #使用__call__方法,可以让对象当成函数被调用
        print(m)
        
        p1=Person('zhangsan',18,178)
        p2=Person('zhangsan',18,178)
        #此时p1和p2指向不同的内存地址,只是里面的内容是一样的
        print('p1的内存地址{},p2的内存地址{}'.format(id(p1),id(p2)))
        
        # is  身份运算符,判断是否是同一个对象,比较的是内存地址
        # ==  使用的时候是调用__eq__方法,默认也是比较内存地址,除非重写
        # !=  使用时调用__ne__方法,或者__eq__方法取反,获取返回值
        print(p1 is p2)
        print(p1==p2)
        
        num1=[1,2,3]
        num2=[1,2,3]
        print('num1的内存地址{},num2的内存地址{}'.format(id(num1),id(num2)))
        print(p1+p2)
        print(p1>p2)
        print(p1*2)
        print(p1-3)
        #result
        是__init__方法,我被调用了
        姓名zhangsan,年龄18,身高178
        <bound method Person.__repr__ of hello world>
        hello world
        47
        是__init__方法,我被调用了
        是__init__方法,我被调用了
        p1的内存地址33243016,p2的内存地址33242888
        False
        True
        num1的内存地址3953160,num2的内存地址3953672
        36
        False
        zhangsanzhangsan
        15
        我是__del__方法,我被调用了
        我是__del__方法,我被调用了
        我是__del__方法,我被调用了
        
    • 内置属性

      • dir() 内置函数获取对象的所有属性

      • _class_ 获取(对象的)类名

      • _dict_ 以字典的形式输出对象的属性名与对应的值

      • _doc_ 获取(对象所在)类的帮助文档

      • _module_ 获取所在的模块名

        class Person(object):
            """
            这是一个人类
            """
            def __init__(self,name,age):
                self.name=name
                self.age=age
        
            def eat(self):
               print('{}正在吃饭'.format(self.name))
        p=Person('zhangsan',18)
        #内置属性
        print(dir(p))   #获取对象的所有属性
        print(p.__class__)  #获取对象的类名
        print(Person.__class__)#获取对象的类名
        print(p.__dict__)  #以字典的形式输出对象的属性名与对应的值
        print(p.__doc__)   #获取对象所在类的帮助文档
        print(Person.__doc__)#获取类的帮助文档
        print(p.__module__)  #获取所在的模块名
        
    • 将对象像字典那么操作

      • __setitem__方法:当出现[]在赋值语句里面时调用

      • __getitem__方法:当出现[]在打印时调用

            def __setitem__(self, key, value):
                #self.key=value  这个代码的意思是给对象增加key这个属性并赋值
                self.__dict__[key]=value
            def __getitem__(self, item):
                return self.__dict__[item]
                
        print(p.__dict__)#以字典的形式输出对象的属性名与对应的值,但每次这么写太麻烦了
        p['name']='Jack'    #如果没用__setitem__方法会报错
        print(p)
        print(p['name'])    #如果没有__getitem__方法会报错
        #result
        {'name': 'zhangsan', 'age': 18}
        name=Jack,age=18
        Jack
        
    • 类属性和对象属性

      • 类属性保存在类里,但不在任何方法或者属性里

      • 可以通过类和对象访问类属性,如果对象的属性没有对应的,会搜索类属性

      • 只能通过类修改类属性

        class Person:
             type='人类'
            def __init__(self,name,age):
                self.name=name
                self.age=age
        #通过类和对象访问类属性
        print(Person.type)
        print(p1.type)
        
        #修改类属性
        p1.type='human'  #不是修改类属性,而是给p1这个对象增加了type的对象属性
        print(p2.type)
        Person.type='monkey'  #修改了类属性
        print(p2.type)
        print(Person.type)
        print(p1.type)   #只有p1没有type属性时,才会返回类属性
        #result
        人类
        人类
        人类
        monkey
        monkey
        human
        
    • 私有变量和私有函数

      • 私有变量

        • 两个下划线开始的变量是私有变量,在内部可以直接访问
        • 定义私有变量的原因
          • 不希望别人访问到,只在内部做;
          • 有了get方法后,可以对这些变量进行额外的操作
        • 想要在外部获取私有变量的方式:直接拿回报错
          • 对象._类名__私有变量
          • 使用get方法:在函数内部定义一个接口
          • 使用property方法获取
      • 私有函数

        • 两个下划线开始的函数称为私有函数,可以内部访问

        • 在外部私有函数不能直接访问

        • 使用对象名._类名__函数()可以强行调用

          import datetime as dt
          class Person(object):
              def __init__(self,name,age):
                  self.name=name
                  self.age=age
                  self.__money=0    #以两个下划线开始的变量是私有变量,在内部可以直接访问,
              def get__money(self): #get方法得到私有变量
                  print('{}查询了余额'.format(dt.datetime.now()))#可以进行额外的操作
                  return self.__money
              def set__money(self,qian):  #set方法修改私有变量
                  self.__money=qian
              def __demo(self):          #以两个下划线开始的函数称为私有函数,可以内部访问
                  print('__demo函数被调用')
              def test(self):
                  self.__demo()
          p1=Person('zhangsan',18)
          #p1.__money  不使用get方法,直接这么写会报错
          print(p1._Person__money)
          print(p1.get__money())
          #类似的使用set方法可以修改私有变量
          p1.set__money(100)  #修改了私有和属性
          print(p1.get__money())
          
          #在外部私有函数不能直接访问
          #p1.__demo            不能直接调用私有函数
          p1._Person__demo()   #使用对象名._类名__函数()可以强行调用
          p1.test()
          
    • 普通方法,静态方法,类方法

      • 普通方法

        • 方法(函数)是存在类里面的,所以可以通过类访问到
        • 实例对象调用方法的时候,是将方法与这个实例对象绑定
        • 使用实例对象名.方法名不需要给形参self传参,self的参数就是实例对象
        • 通过类调用函数的时候需要给self指定实例对象
        class Person(object):  #定义一个Person类
            def __init__(self,name,age):
                self.name=name
                self.age=age
            def eat(self,food):
                print('{}正在吃{}'.format(self.name,food))
        p1=Person('zhangsan',18)
        p2=Person('lisi',19)
        print(p1.eat)
        print(p2.eat)
        print(p1.eat is p2.eat)  #这两个不一样,是类的函数与不同的实例对象绑定
        print(Person.eat)
        Person.eat(p1,'红烧牛肉泡面')#需要指定一个实例对象
        #result
        <bound method Person.eat of <__main__.Person object at 0x00000000021CE088>>
        <bound method Person.eat of <__main__.Person object at 0x00000000021CE188>>
        False
        <function Person.eat at 0x00000000021CF168>
        zhangsan正在吃红烧牛肉泡面
        
      • 静态方法

        • 创建方法的时候,默认是对象方法
        • 如果创建的方法不需要对象的值,那么可以定义成static,使用**@staticmethod**
        • 一般用在我们将一些工具打包成一个类
        • 静态方法,可以通过对象和类调用
        class Person(object):  #定义一个Person类
            def __init__(self,name,age):
                self.name=name
                self.age=age
            def eat(self,food):#创建方法的时候,默认是对象方法
                print('{}正在吃{}'.format(self.name,food))
            #如果创建的方法不需要对象的值,那么可以定义成static
            @staticmethod
            def demo():
                print('hello')
        p1=Person('zhangsan',18)
        p1.demo()
        Person.demo()
        class Calcualator(object): #定义一个计算器
            @staticmethod
            def add(a,b):
                return a+b
            @staticmethod
            def minus(a,b):
                return a-b
            @staticmethod
            def mul(a,b):
                return a*b
            @staticmethod
            def division(a,b):
                return a/b
        print(Calcualator.add(1, 2))
        
      • 类方法

        • 如果定义的方法只和类属性相关,可以定义成类方法,使用**@classmethod**
        • cls就是类,可以在定义的类方法里,使用这个类,就想self一样
        class Person(object):  #定义一个Person类
            type='human'
            def __init__(self,name,age):
                self.name=name
                self.age=age
            def eat(self,food):#创建方法的时候,默认是对象方法
                print('{}正在吃{}'.format(self.name,food))
            #如果定义的方法只和类属性相关,可以定义成类方法
            @classmethod
            def test(cls):#这个cls就是类
                print(type)
                print(cls.type)
        p1=Person('zhangsan',18)
        #类方法可以通过类和对象调用
        p1.test()
        Person.test()
        #result
        <class 'type'>
        human
        <class 'type'>
        human
        
        

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值