Python基础---面向对象

面向对象编程详解
本文深入讲解面向对象编程的基础概念,包括类与对象的关系、属性与方法的管理、静态方法及属性的应用、组合与继承特性、多态与封装原理等。同时介绍了如何利用Python语言特性实现这些面向对象编程技巧。
面向对象:
 1.面向对象的设计/面向对象的编程
 
 2.类相关:
  *dir(类名):查看类属性,返回形式是列表,列表前面的类似'__str__'的
     属性都是系统内置的,自定义的属性与方法名会在列表的最后显示。
  *__dict__:返回值['属性':'属性值','函数名':'函数地址',...]
   类名.__dict__.['属性']-->属性值
   类名.__dict__.['函数名'](参数)-->调用相对应的函数
  *__name__:显示类名
  *__doc__:显示类中的注释
   
 3. 对象相关:对象=类名() #实现类对象的创建,有无参数取决于__init__()方法的参数!
 
 4.类属性/实例属性
  *类属性:类属性又称静态变量,与类对象进行绑定,但是不依赖类对象(依赖类本身),且独有一份!(相当于static修饰的变量)
   *类属性的CRUD:
    class Person:
     name="pzz1"
     def __init__(self):
      pass
     #查看
     print(Person.name)
     #添加
     Person.age=10
     print(Person.__dict__)
     #修改
     Person.age=1
     print(Person.__dict__)
     #删除
     del Person.age
     print(Person.__dict__)
   *类方法的CRUD:
    class Person:
     name = "pzz1"
     def __init__(self):
      pass
     def have_food(self,food):
      print("Have %s"%food)
    p1=Person()
    #添加
    def strong_body(self):
     print("strong_body")
    Person.strong=strong_body
    p1.strong()
    print(Person.__dict__)
    #修改
    def strong_body2(self):
     print("strong_body2")
    Person.strong=strong_body2
    p1.strong()
    print(Person.__dict__)
    #删除
    del Person.strong
    print(Person.__dict__)
  *实例属性:1.注意实例属性与类属性区别,实例属性是self.后面的属性,而类属性前面没有self,类属性可以理解为Java里面的静态属性!
       2.实例还是可以调用类属性是因为静态变量的特点(静态变量有所有类对象共享,但是只有一份,依赖于类本身,不依赖类对象)
       3.类对象只有实例属性,类属性与方法都是只有一份的,在类本身当中,而之所以类对象可以调用类方法,是因为类方法参数列表
         中的self作用,类对象调用方法时,self会被初始化类对象的地址!从而实现类对象对类方法的调用!
    实例属性的CRUD:
     class Person:
      def __init__(self,name,age):
       self.name=name
       self.age=age
      def have_food(self):
       print("Hava food!")
     p1=Person("pzz",18)
     #查看实例属性
     print(p1.__dict__)
     #添加实例属性
     p1.gender="Boy"
     print(p1.__dict__)
     #修改实例属性
     p1.gender="Girl"
     print(p1.__dict__)
     #删除实例属性
     del p1.gender
     print(p1.__dict__)
    注意:实例的属性可以进行CRUD,方法也可以,但是一般不建议做!
 5.实例属性/类属性/普通变量
  注意点1:
  name="-->>pzz1"
  class Person:
   name="pzz2" #属于类属性
   def __init__(self,age,gender):
    self.age=age
    self.gender=gender #属于实例属性
    print(name) #属于普通变量(***注意这个点,容易搞混)
  p1=Person(18,"Boy")
  print(p1.name,Person.name)
  
  注意:1.类里面定义的变量是类属性,可以通过类名.__dict__的方式查看
        2.__init__()方法里面的self.后面的属性属于实例属性,可以通过类对象.__dict__的方式查看
        3.上述__init__()方法里面的name,不属于实例属性/类属性的任意一种,所以不会在实例和类里面查看,会去上一级直到全局查看!
  
  注意点2:
   class Person:
    name="pzz1"
    age=[1,2]
    def __init__(self):
     pass
   p1=Person()
   p1.name="pzz2" #注意这里面不会对类属性进行修改,只是增加了一个实例属性而已!
   print("类属性-->%s"%Person.name,p1.name)
   
   class Person:
   name="pzz1"
   age=[1,2]
   def __init__(self):
    pass
   p1=Person()
   p1.age.append(3) #修好了类属性
   print("类属性-->%s"%Person.age,p1.age)
   
   总结:一般情况下,做赋值操作的都不会修改类属性!
 6.
  *静态属性装饰器:@property
  *静态方法装饰器:@staticmethod
  *类方法装饰器:@classmethod
  例子:
  class Person:
  name="pzz"
  def __init__(self):
   pass
  @property
  def have_food(self):
   print("have_food")
  @staticmethod
  def have_food2(a,b):
   print("have_food2",a,b)
  @classmethod
  def have_food3(cls):
   print("have_food3",cls.name)
  p1=Person()
  #注意@property装饰方法,默认有参数self,在调用方法时,不需要加()
  p1.have_food
  #@staticmethod 静态方法,不能访问类属性与实例属性,就是一个类的工具包
  #之所以不能访问类属性与实例属性,是因为该装饰器修饰的方法没有cls或是self默认参数
  # 可以使用类名调用或是实例调用
  Person.have_food2("apple","orange")
  p1.have_food2("apple","orange")
  #@classmethod 装饰器会给方法加上默认参数cls,方便访问类属性,类似self
  #又因为类属性实例都可以访问,所以在实例调用该方法时,cls初始化为类对象,访问
  #相应的属性与方法(类属性/类方法,实例都可以访问)
  Person.have_food3()
  p1.have_food3()
 7.组合:Python中的组合就是在类对象里面嵌套一个或是多个其他类对象
 8.面向对象的三大特性
  *继承:
   1).子类继续父类的所有属性,但是如果子类定义的属性与父类属性重名,并不会覆盖,而是各自待在自己的__dict__中.
   2).接口继承
    import abc
    #接口类,且方法必须全是抽象方法
    #继承接口的类,全部实现抽象方法的是普通类,否则为抽象类
    #抽象类是不可以创建对象的,当然接口也不可以
    class Dad(metaclass=abc.ABCMeta):
     @abc.abstractmethod
     def make_money(self):
      print("make money")
     @abc.abstractmethod
     def make_child(self):
      print("make child")
   3).继承顺序
    *继承顺序参照类的MRO表(MRO表就是类的祖先)
    *继承时,调用属性或是方法时,遵循的原则:
     1.子类会优先于父类被检查
     2.多个父类会依据它们在MRO表中的顺序
    *Python3都是新式类,继承顺序遵循广度优先的原则;而在Python2中,有新式类与经典类之分
     经典类:没有任何的基类(即class 类名:这种形式的,没有小括号的),但是经典类的子孙全是经典类!
       继承顺序遵循深度优先原则,而且此类没有MRO列表!
     新式类:存在任意基类!继承顺序同Python3!
   4).子类调用父类的方法
    class Dad():
     def __init__(self,name,age):
      self.name=name
      self.age=age
     def make_money(self):
      print("Dad make money!")
    class Son(Dad):
     def __init__(self,name,age,gender):
      #方式一:super().__init__(name,age)
      #方式二:super(Son,self).__init__(name,age)
      #方式三:Dad.__init__(self,name,age)
      self.gender=gender
     def consume_money(self):
      #super().make_money()
      #super(Son, self).make_money()
      Dad.make_money(self)
      print("Son consume money!")
    注释:推荐方式一
  *多态:多态的前提是继承,继承实现不同的对象拥有相同的方法,从而实现不同的类对象执行相同的方法(运行时的多态)
    (理解的浅显,作者个人理解不透彻,请大牛多多指教)
  *封装:
   方式一:
    class Dad:
     _gender="Boy" #通过_方式,把变量约定为私有,但是类的外部依旧可以访问
     def __init__(self,name,age):
      self.name=name
      self.age=age
     def get_gender(self):
      return self._gender
    d1=Dad("plq",43)
    print(d1.get_gender(),d1._gender)
   方式二:
    class Dad:
     # 通过_方式,把变量约定为私有
     # 类的外部不可以原样访问,但是可以通过_Dad__gender的方式访问.
     #当变量被定义为__变量时,类会把其转换为_类名__变量!
     #类的内部原样访问
     __gender="Boy"
     def __init__(self,name,age):
      self.name=name
      self.age=age
     def get_gender(self):
      return self.__gender
    d1=Dad("plq",43)
    print(d1.get_gender(),d1._Dad__gender)
注意:私有属性与私有方法,定义或是使用都是一致的!

9.反射

 *定义:程序可以访问、检测和修改自身状态或行为的一种能力
 *实现反射的函数:
  hasattr(object,args):判断object中是否有参数argv对应的方法或是属性
  getattr(object,name,default=None)
  setattr(x,y,v)
  delattr(x,y)
  上述方法适应于类或是对象
  class Dad:
   gender="Boy"
   def __init__(self,name,age):
    self.name=name
    self.age=age
   def make_money(self):
    print("make_money")
  d1=Dad('plq',18)
  #判断类或是实例中是否存在对应属性(方法)或是是否可以访问到对应属性(方法)!
  # print(hasattr(d1,'gender'))
  # print(hasattr(Dad,'gender'))
  # print(hasattr(d1,'make_money'))
  # print(hasattr(Dad,'make_money
  
  #给类或是对象设置属性
  setattr(d1,"hobby","basketball")
  print(d1.__dict__)
  setattr(Dad,"character","acute")
  print(Dad.__dict__)
  
  #给类或是对象设置方法
  setattr(d1,"test1",lambda x:x+1)
  setattr(Dad,"test2",lambda x:x-1)
  
  #获得类或是对象的属性值(获取方法时,返回的是函数地址)
  print(getattr(d1,"hobby"))
  print(getattr(Dad,"character"))
  getattr(d1,"make_money")()
  getattr(Dad,"make_money")(d1)
  #如果获取的属性或是方法不存在,错误信息提示是第三个参数的内容!
  print(getattr(d1,"hobby1","没有hobby1属性"))
  print(getattr(Dad,"character1","没有character1"))
  
  #删除属性(或是方法)
  delattr(d1,"hobby")
  delattr(Dad,"character")
  print(d1.__dict__)
  print(Dad.__dict__)

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值