设为首页 收藏本站
查看: 918|回复: 0

[经验分享] python面向对象基础语言进阶

[复制链接]

尚未签到

发表于 2018-8-8 13:09:10 | 显示全部楼层 |阅读模式
  在此感谢前辈们的指导:http://python.jobbole.com/80955/
  https://www.cnblogs.com/wupeiqi/p/4766801.html
  https://www.cnblogs.com/paomaliuju/p/5122761.html
  https://www.cnblogs.com/goser/articles/7097728.html
  http://www.cnblogs.com/alex3714/articles/5213184.html
  https://www.cnblogs.com/cenyu/p/5713686.html
  本文是各篇文章优点的综合,适合有一定基础的朋友进行个人知识梳理
  为了表示对前辈们的尊敬,以下均为纯手打,代码已经在2.7和3.6.3版本的python中测试过,并进行了修改,和注释整理,以确保最通俗易懂。
  首先回顾一下上节知识点
  1,面向对象是一种很重要的编程方式,此编程方式的实现主要是通过类和对象的使用来实现的
  2,在类中储存有多个需要的函数
  3,对象,使用类这个模板,来进行更加具体的实例化,主要用于调用被包装在类中的函数。
  4,面向对象三大属性:封装,继承和多态
  5,python中新式类和经典类的粗浅比较用法
  6,深度优先和广度优先的第一核心概念解释以及第二爬虫中具体运用的解释。
  那么这次分享,将会是如下部分:
  面向对象高级语法部分

  •   经典类vs新式类核心  
  •   字段,属性
  •   静态方法、类方法、属性方法
  •   类的特殊方法
  •   反射
  谢谢大家啦(微笑)。
  第一部分:
  五星级:经典类和新式类的比较用法(重要)
  (注:经典类的代码有的需要在2.7中运行,请提前下好)
  在python2及以前的版本中,由任意内置类型派生出来的类(只要有一个内置类型位于类树的某个位置)都属于新式类,反之,即不由任意内置类型派生出来的类,则称之为“经典类”。
  关于内置类型的名词解释:
  新式类”和“经典类”的区分在python3
  “内置类型是指任何语言在设计初期定义的类型,如c语言中的int, double, char... 它也是在一种语言中最基本的类型,
  与编译器编译出的代码具有重大关系.
  "新式类"和“经典类”的区分在python3中就已经不存在了,而在之后的版本里,所有的类都派生出了自类置类型object,即所有的类都是新式类
  经典类继承算法是深度优先,新式类则是广度优先
  class  A():#此代码在2.7.14中运行,也可以在3.6.3中运行,但是许多大型的经典类实例,只能在2.7中运行

  var='classic>  class B(A):
  pass
  class C():
  var='class C'
  class sunclass(B,C):
  pass
  if __name__=='__main__':
  print(sunclass.var)

  最后结果:classic>  再来看新式类
  class  A(object):

  var='classic>  class B(A):
  pass
  class C(A):
  var='class C'
  class sunclass(B,C):
  pass
  if __name__=='__main__':
  print(sunclass.var)
  最后结果:class C
  这恰好就是上节分享的深度优先和广度优先
  但是值得注意的是,新式类并非全部都是广度优先,而是采用c3算法(这一部分以后继续进行介绍)
  可是为什么python3之中,会出现新式类呢,经典类用的不是挺好的吗,这个需要通过具体问题来进行分析
  在经典类中所有的类都是classobj类型,而类的实例是instance类型,类与实例只有通过__class__属性进行关联,这样在判断实例时,就会造成不便,所有的类都是instance类型
  class A():pass#此代码在python32.7中运行
  class B():pass
  a = A()
  b = B()
  if __name__ == '__main__':
  print(type(a))
  print(type(b))
  print(type(a) == type(b))
  最后结果
  <type 'instance'>
  <type 'instance'>
  True
  type(a) == type(b)的结果永远为True,那这样的比较就毫无意义。
  更为麻烦的是,经典类的实例是instance类型,而内置类的实例却不是,无法统一。
  但是在python3中却没有这样的要求
  同样代码,在python3中的运行结果
  <class '__main__.A'>
  <class '__main__.B'>
  False
  综上:
  Python3中所有的类都是新式类,新式类中类与类型已经统一:类实例的类型是这个实例所创建自的类(通常是和类实例的__class__相同),而不再是Python 2.x版本中的“instance”实例类型。
  五星级:字段,属性(重要)
  字段分为,静态字段和普通字段
  静态字段:属于类
  普通字段:属于对象,
  让我们来通过一个小代码,了解什么是静态字段,和普通字段
  class Provinces:
  #静态字段
  country='中国'
  def __init__(self,name):
  self.name=name#普通字段
  #直接访问普通字段
  obj=Provinces('河北省')
  print(obj.name)
  #直接访问静态字段
  print(Provinces.country)
  静态字段在内存中只保存一份
  普通字段在每个对象中都要保存一份
  属性:
  属性有两个知识点:
  1,属性的基本使用
  2,属性的两种定义方式
  一:属性的基本使用:
  class Foo:
  def func(self):
  print('求魔')
  #定义属性
  @property#定义属性之前的必须操作
  def pro(self):
  return "wu pei qi"
  foo_obj=Foo()
  foo_obj.func()
  c=foo_obj.pro
  print(c)
  属性的定义和调用注意以下几点:
  1:定义时,在普通方法的基础上调用@property方法
  2:定义时,属性中仅有一个self函数
  3:调用时无需括号
  foo_obj.func()
  c=foo_obj.pro
  属性存在意义是:访问属性时可以制造出和访问字段完全相同的假象
  属性由方法变种而来,如果Python中没有属性,方法完全可以代替其功能。
  实例:对于主机列表页面,每次请求不可能把数据库中的所有内容都显示到页面上,而是通过分页的功能局部显示,所以在向数据库中请求数据时就要显示的指定获取从第m条到第n条的所有数据(即:limit m,n),这个分页的功能包括:
  根据用户请求的当前页和总数据条数计算出 m 和 n
  根据m 和 n 去数据库中请求数据
  class Pager:
  def __init__(self,current_page):
  #用户当前请求的页码(第一页,第二页...)
  self.current_page=current_page
  #每页默认显示10条数据
  self.per_items=10
  @property
  def start(self):
  val=(self.current_page-1)*self.per_items
  return val
  @property
  def end(self):
  val=self.current_page*self.per_items
  return val
  p = Pager(1)
  print(p.start)#就是起始值,即:m
  print(p.end) #就是结束值,即:n
  属性的两种定义方式
  1,装饰器 即:在方法上运用装饰器
  2,静态字段 ,即在类中定义值为property对象的静态字段
  第一种装饰器方式:(在类的普通方法上应用@property装饰器
  (此处只介绍新式类的方法)
  #新式类:
  class Goode(object):
  @property
  def price(self):
  print('@property')
  @price.setter
  def price(self, value):
  print('@price.setter')
  @price.deleter
  def price(self):
  print('@price deleter')
  obj=Goode()
  obj.price
  obj.price=123
  del obj.price      # 自动执行 @price.deleter 修饰的 price 方法
  新式类中的属性有三种访问方式,并分别对应了三个被@property、@方法名.setter、@方法名.deleter修饰的方法
  由于新式类中具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除
  class Goode(object):
  def __init__(self):
  #原价
  self.original_price=100
  #折扣
  self.discount=0.8
  @property
  def price(self):
  #实际价格=原价*折扣
  new_price=self.original_price*self.discount
  return new_price
  @price.setter
  def price(self,value):
  self.original_price=value
  print('%s'%(value))
  @price.deleter
  def price(self,value):
  del self.original_price
  obj=Goode()
  print(obj.price)
  obj.price=81
  静态字段方式,创建值为property对象的静态字段
  class Foo:
  def get_bar(self):
  return 'wupeiqi'
  BAR=property(get_bar)
  obj=Foo()
  result=obj.BAR
  print(result)
  这是一个小实例
  我们再来看一个蛮经典的实例
  class Foo(object):
  def __init__(self,name):
  self.name=name
  def get_bar(self):
  return self.name
  def set_bar(self,value):
  self.name=value
  def del_bar(self):
  del self.name
  BAR=property(get_bar,set_bar,del_bar,'desadfas')
  obj = Foo('100')
  print(obj.BAR)  # 自动调用第一个参数中定义的方法:get_bar
  obj.BAR = "alex"#print(obj.)# 自动调用第二个参数中定义的方法:set_bar方法,并将“alex”当作参数传入
  print(obj.BAR)
  del Foo.BAR  # 自动调用第三个参数中定义的方法:del_bar方法,进行删除
  class Goods(object):
  def __init__(self):
  self.origina_price=100
  self.discount=0.8
  def get_price(self):
  new_price=self.origina_price*self.discount
  return new_price
  def set_price(self,value):
  self.original_price = value
  def del_price(self):
  del self.original_price
  PRICE = property(get_price, set_price, del_price, '价格属性描述...')
  obj = Goods()
  obj.PRICE         # 获取商品价格
  obj.PRICE = 200   # 修改商品原价
  del obj.PRICE     # 删除商品原价
  第三部分:静态方法、类方法、属性方法
  1,静态方法
  简单理解:通过@staticmethod装饰器即可把其装饰的一个方法转变为静态方法,但什么是静态方法,普通方法必须实例化之后才能调用,但是静态方法,已经跟类本身没有关系,它与类的为唯一关联是需要通过类名才能调用这个方法
  class Dog(object):
  def __init__(self,name):
  self.name=name
  @staticmethod
  def eat(self):
  print("%s is eating"%self.name)
  d=Dog("dsfas")
  d.eat()
  上述会出现一系列错误
  因为当eat变成静态方法后,再通过实例调用时就不会自动把实例本身当作一个参数传给self了。
  而要解决它的方式有两种
  一个是把d当成self传入当中
  另一个就是把self去掉
  class Dog(object):
  def __init__(self,name):
  self.name = name
  @staticmethod
  def eat():
  print(" is eating")
  d = Dog("ChenRonghua")
  d.eat()
  即可
  2,类方法
  类方法通过@classmethod装饰器实现,类方法和普通方法的区别是, 类方法只能访问类变量,不能访问实例变量
class Dog(object):  def __init__(self,name):
  self.name=name
  @classmethod
  def eat(self):
  print("%s is eating" %self.name)
  d=Dog("chenronghua")
  d.eat()
  这段代码,执行时会进行报错
  所以,我们需要定义一个类变量
class Dog(object):  name = "我是类变量"
  def __init__(self, name):
  self.name = name
  @classmethod
  def eat(self):
  print("%s is eating" % self.name)
  d = Dog("ChenRonghua")
  d.eat()
  3,属性方法
  刚才我们提到了属性变量,其实属性变量就是属性方法
  这次我们来做一个小案例
  比如 ,你想知道一个航班当前的状态,是到达了、延迟了、取消了、还是已经飞走了, 想知道这种状态你必须经历以下几步:
  1. 连接航空公司API查询
  2. 对查询结果进行解析
  3. 返回结果给你的用户
lass Flight(object):  def __init__(self,name):
  self.flight_name=name
  def checking_status(self):
  #print('检查飞机的运行状态:'%self.flight_name)
  return 1
  @property
  def flight_status(self):
  status=self.checking_status()
  if status==0:
  print('飞机取消了')
  elif status==1:
  print('飞机飞行之中')
  elif status==2:
  print('飞机降落了')
  else:
  print("不能够证明飞机的运行状态")
  @flight_status.setter
  def flight_status(self,status):
  status_dic={
  0:"canceled",
  1:"arrived",
  2:"depatured"
  }
  print("\033[31;1m已经修改了飞行的状态到 \033[0m", status_dic.get(status))
  @flight_status.deleter
  def flight_status(self):
  print("status got removed")
  f=Flight("波音777")
  f.flight_status
  f.flight_status=2
  好了,非常基础的东西就讲完了,我们来讲一点比较偏门的,毕竟学习一门语言还要了解他的一些源代码,知道是怎样运行的,才能不断精进
  类的特殊成员用法:
  1,__doc__:表示类的描述信息:
  在开发中,我们需要在代码中多加注释,来增强代码的可读性,用__doc__就可以查看函数或类的描述信息
def test():  '''
  this is a test function
  '''
  pass

  class>  '''

  this is a>  '''
  print(test.__doc__)
  print(ClassTest.__doc__)
  这个函数可以用来查看注释
  2、__module__和__class__
  __module__ 表示对象所在的模块
  __class__  表示对象所在的类是什么
  3,__init__ 构造方法,通过类创建对象时,自动触发执行
  5. __call__ 对象后面加括号,触发执行。
  注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()
class Foo:  def __init__(self):
  pass
  def __call__(self, *args, **kwargs):
  print('call')
  obj=Foo()
  obj()
  6.__dict__ 查看类或对象中的所有成员
class Province:  country='China'
  def __init__(self,name,count):
  self.name=name
  self.count=count
  def func(self,*args,**kwargs):
  print('func')
  print(Province.__dict__)#获取类的成员,静态字段,方法
  obj1=Province('HeBei',10000)
  print(obj1.__dict__)#获取obj1的成员
7.__str__ 如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值
class Foo:     def __str__(self):        return 'alex li'  obj = Foo()print (obj)# 输出:alex li8.__getitem__、__setitem__、__delitem__
  用于索引操作,如字典。以上分别表示获取、设置、删除数据
class Foo(object):  def __getitem__(self, item):
  print('__getitem',item)
  def __setitem__(self, key, value):
  print('__setitem__',key,value)
  def __delitem__(self, key):
  print('__delitem__',key)
  obj=Foo()
  result=obj['k1']
  obj['k2']='alex'
  del obj
  最后一部分:
反射即想到4个内置函数分别为:getattr、hasattr、setattr、delattr  获取成员、检查成员、设置成员、删除成员  现对这几个函数进行细致的分享,
  getattr(object, name[,default])
  获取对象object的属性或者方法,如果存在即打印出来,如果不存在,即打印出默认值,默认值可选
  需要注意的是,如果返回的是对象的方法,返回的是方法的内存地址,如果运行这个方法,可以在后面添加一对括号
class test():  name="xiaohua"
  def run(self):
  print( "helloworld")
  t=test()
  print(getattr(t,"name"))#获取name属性,存在就打印出来。
  print(getattr(t, "run"))  #获取run方法,存在就打印出方法的内存地址。
  getattr(t, "run")()  #获取run方法,后面加括号可以将这个方法运行。
  print(getattr(t, "age","18"))  #若属性不存在,返回一个默认值。
hasattr(object, name)  判断一个对象里面是否有name属性或者name方法,返回BOOL值,有name特性返回True, 否则返回False。需要注意的是name要用括号括起来
class test():  name="xiaohua"
  def run(self):
  print( "helloworld")
  t=test()
  print(hasattr(t,"name"))#判断对象有name属性
  print(hasattr(t, "run"))  #判断对象有run方法
  setattr(object, name, values)
  给对象的属性赋值,若属性不存在,先创建再赋值
class test():  name="xiaohua"
  def run(self):
  print( "helloworld")
  t=test()
  print(hasattr(t,"age"))#判断属性是否存在
  setattr(t, "age", "18")   #为属相赋值,并没有返回值
  print(hasattr(t, "age") )   #属性存在了
  综合运用
  class Foo(object):
  def __init__(self):
  self.name = 'wupeiqi'
  def func(self):
  return 'func'
  obj = Foo()
  #### 检查是否含有成员 ####
  print(hasattr(obj, 'name'))
  print(hasattr(obj, 'func'))
  #### 获取成员 ####
  getattr(obj, 'name')
  getattr(obj, 'func')
  #### 设置成员 ####
  setattr(obj, 'age', 18)
  setattr(obj, 'show', lambda num: num + 1)
  #### 删除成员 ####
  delattr(obj, 'name')
  #delattr(obj, 'func')#不能用于删除方法,否则报错

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-548705-1-1.html 上篇帖子: python笔记(猜拳游戏) 下篇帖子: 6.Python深浅拷贝
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表