Python【系列教程】之类和对象

举报
小米粒-biubiubiu 发表于 2020/11/29 00:27:33 2020/11/29
3.5k+ 0 0
【摘要】 一、定义类,对象,实例方法和自动绑定self class Person: hair = 'black' # 构造方法 def __init__(self, name='Charlie', age=8): self.name = name self.age = age # 定义一个say方法 def say(self, content): print(content) ...

一、定义类,对象,实例方法和自动绑定self


      class Person:
       hair = 'black'
      # 构造方法
      def __init__(self, name='Charlie', age=8):
       self.name = name
       self.age = age
      # 定义一个say方法
      def say(self, content):
       print(content)
      p = Person()
      print(p.name, p.age)
      p.name = '李刚'
      p.say('语言简单,学习很容易')
      print(p.name, p.age)
      p.skills = ['programming', 'swimming']
      print(p.skills)
      del p.name
      # 删除p对象的name属性,再次访问的时候报错
      # print(p.name)
      # 动态给对象增加方法
      def info(self):
       print("--info函数--", self)
      p.foo = info
      p.foo(p)
      p.bar = lambda self: print('--lambda表达式--', self)
      p.bar(p)
      """上面分别用函数和lambda表达式为p对象动态增加了方法,但是对于动态
      增加的方法,python不会自动将方法调用者绑定到它们的第一个参数,因此程序必须手动为第一个参数
      传入参数值"""
      """如果希望动态增加的方法也能自动绑定到第一个参数,则可借助于types模块下的MethodType进行包装"""
      def intro_func(self, content):
       print("我是一个人,信息为:%s" % content);
      # 导入MethodType
      from types import MethodType
      p.intro = MethodType(intro_func, p)
      p.intro("生活在别处");
  
 

二、方法


      class Bird:
      # 使用@Classmethod修饰的方法是类方法
       @classmethod
      def fly(cls):
       print('类方法fly:', cls)
      # 使用@staticmethod修饰的方法是静态方法
       @staticmethod
      def info(p):
       print('静态方法info:', p)
      Bird.fly()
      Bird.info("crazy")
      b = Bird()
      b.fly()
      b.info("kit")
      """前面的静态方法和类方法的本质就是函数装饰器,
      其中classmethod和staticmethod都是python内置的函数"""
      def funA(fn):
       print('A')
       fn()  # 执行传入的fn参数
      return 'end'
      @funA
      def funB():
       print('B')
      print(funB)
      """上面的程序@funA修饰funB,这意味着程序要完成两步操作
      将funB作为funA()的参数,也就是上面的粗体字码相当于执行funA(funB)
      将funB替换成第1步执行的结果,funA()执行完成后返回fkit,因此funB
      就不再是函数,而是被替换成一个字符串
      """
      def foo(fn):
      # 定义一个嵌套函数
      def bar(*args):
       print("====1====", args)
       n = args[0]
       print('====2====', n * (n - 1))
      # 查看传给foo函数的fn函数
       print(fn.__name__)
       fn(n * (n - 1))
       print("*" * 15)
      return fn(n * (n - 1))
      return bar
      @foo
      def my_test(a):
       print('====my_test函数====', a)
      print(my_test)
      my_test(10)
      my_test(6, 5)
      # def auth(fn):
      # def auth_fn(*args):
      # print("模拟执行权限检查")
      # fn(*args)
      #
      # return auth_fn
      def auth(fn):
      def auth_fn(*args):
       print("模拟执行权限检查")
       fn(*args)
      return auth_fn
      @auth
      def test(a, b):
       print("asdasdasdasd啊实打实大苏打")
      test(20, 15)
      """上面介绍的这种在被修饰函数之前,之后,抛出异常后增加某种处理逻辑的方式
      就是其他编程语言中的aop面向切面编程
      """
      class item:
       print('正在定义item类')
      for i in range(10):
      if i % 2 == 0:
       print('偶数',1)
      else:
       print('奇数',1)
      global_fn = lambda p:print('执行lambda表达式,p参数',p)
      class category:
       cate_fn = lambda p:print('执行lambda表达式,p参数',p)
      global_fn('fkit')
      c = category()
      c.cate_fn()
  
 

三、成员变量


      # 1.使用property函数定义属性
      class Rectangle:
      def __init__(self, width, height):
       self.width = width
       self.height = height
      def setSize(self, size):
       self.width, self.height = size
      def getSize(self):
      return self.width, self.height
      def delSize(self):
       self.width, self.height = 0, 0
       size = property(getSize, setSize, delSize, '用于描述矩形大小的属性')
      print(Rectangle.size.__doc__)
      help(Rectangle.size)
      rect = Rectangle(4, 3)
      # 相当于调用了getSize方法
      print(rect.size)
      rect.size = 9, 7
      print(rect.width)
      print(rect.height)
      # 删除size,相当于删除了width属性和height属性
      del rect.size
      print(rect.width)
      print(rect.height)
      """在某些编程语言中,类似于这种property合成的属性被称为计算属性。这种属性
      并不真正存储任何状态,它的值其实是通过某种算法计算得到的,当程序对该属性赋值时,
      被赋的值也会被存储到其他实例变量中
      """
      """还可以使用@property装饰器来修饰方法,使之成为属性"""
      class Cell:
      # 使用@property装饰器来修饰方法,相当于为该属性设置getter方法
       @property
      def state(self):
      return self._state
      # 为state属性设置setter方法
       @state.setter
      def state(self, value):
      if 'alive' in value.lower():
       self._state = 'alive'
      else:
       self._state = 'dead'
      # 为is_dead属性设置getter方法
      # 只有getter方法的属性是只读属性
       @property
      def is_dead(self):
      return not self._state.lower() == 'alive'
      c = Cell()
      c.state = 'Alive'
      print(c.state)
      print(c.is_dead)
      ##################隐藏和封装################
      class User:
      def __hide(self):
       print("示范隐藏的hide方法")
      def getname(self):
      return self.__name
      def setname(self, name):
      if len(name) < 3 or len(name) > 8:
      raise ValueError('用户名必须在3~8之间')
       self.__name = name
       name = property(getname,setname)
      u = User()
      #__hide其实是python悄悄修改了方法名,将__hide修改成了_类名__hide()
      u._User__hide()
      u._User__name = 'fk'
      print(u.name)
      """如果程序希望python类中的某些成员隐藏起来,那么只要让该成员的名字以双下划线开头即可。
      即使通过这种机制实现了隐藏,其实也依然可以绕过去"""
  
 

四、类的继承


      # 1.类的继承
      class Fruit:
      def info(self):
       print('我是一个水果!重%g克' % self.weight)
      class Food:
      def taste(self):
       print("不同食物的口感不同")
      # 定义Apple类,继承了Fruit和Food类
      class Apple(Fruit, Food):
       pass
      a = Apple()
      a.weight = 5.6
      # 调用水果类的info方法
      a.info()
      # 调用食物类的taste方法
      a.taste()
      class Item:
      def info(self):
       print("item中方法:", '这是一个商品')
      class Product:
      def info(self):
       print("Product中方法:", "这是一个工业产品")
      class Mouse(Item, Product):
       pass
      m = Mouse()
      m.info()
      """Mouse继承了两个类,两个类具有相同的方法,但是Item排在Product的前面,
      因此Item中定义的方法优先级更好,Python会优先到Item父类中搜寻方法,一旦
      在Item父类中搜寻到目标方法,Python就不会继续向下搜寻了"""
      # 重写父类的方法
      class Bird:
      # Bird类的fly()方法
      def fly(self):
       print('我在天空里自由自在的飞翔')
      class Ostrich(Bird):
      def fly(self):
       print('我只能在地上奔跑')
      # 创建Ostrich
      os = Ostrich()
      # 执行子类的fly方法,将输出我只能在地上奔跑
      os.fly()
      class BaseClass:
      def foo(self):
       print('父类中定义的foo方法')
      class SubClass(BaseClass):
      def foo(self):
       print("子类重写父类中的foo方法")
      def bar(self):
       print('执行bar方法')
      self.foo()
      # 使用类名调用实例方法(未绑定方法)调用
       BaseClass.foo(self)
      sc = SubClass()
      sc.bar()
      # 使用super函数重写父类构造方法
      class Employee:
      def __init__(self, salary):
      self.salary = salary
      def work(self):
       print('普通员工正在写代码,工资是:', self.salary)
      class Customer:
      def __init__(self, favorite, address):
      self.favorite = favorite
      self.address = address
      def info(self):
       print('我是一个顾客,我的爱好是:%s,地址是: %s' % (self.favorite, self.address))
      class Manager(Employee,Customer):
      def __init__(self,salary,favorite,address):
      super(Manager,self).__init__(salary)
       Customer.__init__(self,favorite,address)
      m=Manager(25000,'it产品','广州')
      m.work()
      m.info()
  
 

五、python的动态性


      ############################################2.动态属性与_slots_
      #动态的给Cat类添加方法
      class Cat:
      def __init__(self,name):
       self.name = name
      def walk_func(self):
       print('%s 慢慢地走过一片草地' % self.name)
      d1 =Cat('Garfield')
      d2 =Cat('Kitty')
      Cat.walk = walk_func
      d1.walk()
      d2.walk()
      class Dog:
       __slots__ = ('walk','age','name','foo')
      def __init__(self,name):
       self.name = name
      def test(self):
       print('预先定义的test方法')
      d = Dog('snooy')
      #只允许为实例动态的添加walk,age,name这三个属性或者方法
      from types import  MethodType
      d.walk = MethodType(lambda self:print('%s 正在慢慢的走'),d)
      d.age = 5
      d.walk()
      d.foo = 30
      #__slots__并不限制通过类来动态添加方法
      Dog.bar = lambda self: print('abc')
      d.bar()
      #####################3.使用type()函数定义类
      def fn(self):
       print("this is a 函数")
      Dog = type('Dog',(object,),dict(walk=fn,age=6))
      #创建Dog对象
      d = Dog()
      print(type(d))
      print(type(Dog))
      d.walk()
      print(Dog.age)
      """type定义类的时候可以指定三个参数
      参数一:创建的类名
      参数二:该类继承的父类集合,由于python 支持多继承,因此此处使用元组指定它的多个父类。即使实际
      只有一个父类,也需要使用元组语法(必须要多一个逗号)
      参数三:该字典对象为该类绑定的类变量和方法。其中字典key就是变量名或者方法名,
      如果字典的value是普通值,那就代表类变量,如果字典的value是函数,则代表方法。
      """
      ###########################4.使用metaclass
      """如果希望创建某一批类全部具有某种特征,可通过metaclass来实现,使用metaclass可在创建类的
      时候动态修改类定义,为了使用metaclass动态修改类定义,程序需要先定义metaclass,metaclass应该继承
      type类,并重写__new__()方法"""
      class ItemMetaclass(type):
      #cls代表被动态修改的类
      #name代表被动态修改的类名
      #bases代表被动态修改的类的所有父类
      #attr代表被动态修改的类的所有属性,方法组成的字典
      def __new__(cls, name,bases,attrs):
       attrs['cal_price'] = lambda self: self.price * self.discount
      return type.__new__(cls,name,bases,attrs)
      class Book(metaclass=ItemMetaclass):
       __slots__ = ('name','price','_discount')
      def __init__(self,name,price):
       self.name = name
       self.price = price
       @property
      def discount(self):
      return self._discount
       @discount.setter
      def discount(self,discount):
       self._discount = discount
      class CellPhone(metaclass=ItemMetaclass):
       __slots__ = ('price', '_discount')
      def __init__(self, price):
       self.price = price
       @property
      def discount(self):
      return self._discount
       @discount.setter
      def discount(self, discount):
       self._discount = discount
      """上面定义的Book类和CellPhone类都指定了metaclass信息,因此当
      python解释器在创建这两个类的时候,ItemMetaClass的__new__方法就会被调用,
      用于修改这两个类,动态增加cal_price方法"""
      b= Book("疯狂python讲义",89)
      b.discount = 0.76
      print(b.cal_price())
      cp = CellPhone(2399)
      cp.discount = 0.85
      print(cp.cal_price())
      """metaclass这个功能在开发一些基础性框架时非常有用,程序可以通过
      使用metaclass为某一批需要具有通用功能的类添加方法"""
  
 

六、多态


      #################1.多态性
      class Bird:
      def move(self, field):
       print('鸟在%s上自由的飞翔' % field)
      class Dog():
      def move(self, field):
       print('狗在%s里飞快地奔跑' % field)
      x = Bird()
      # 调用x变量
      x.move('天空')
      x = Dog()
      x.move('草地')
      class Canvas:
      def draw_pic(self, shape):
       print('---开始绘图---')
       shape.draw(self)
      class R:
      def draw(self, canvas):
       print('在%s上绘制矩形' % canvas)
      class T:
      def draw(self, canvas):
       print('在%s上绘制三角形' % Canvas)
      class Circle:
      def draw(self, canvas):
       print('在%s上h绘制圆形' % canvas)
      c = Canvas()
      c.draw_pic(R())
      c.draw_pic(T())
      #################2.检查类型
      """python提供了两个函数来检查类型
      issubclass(cls,class_or_tuple):检查cls是否是后一个类或者元组包含的多个类中任意类的子类
      isinstance(obj,class_or_tuple):检查obj是否是后一个类或者元组包含的多个类中任意类的对象
      通过使用上面两个函数,程序可以方便地先执行检查,然后才调用方法,这样可以保证程序不会出现
      意外情况
      """
      hello = "hello"
      print(isinstance(hello, str))
      print(issubclass(str, object))
      print(isinstance(hello, tuple))
      class A:
      pass
      class B:
      pass
      class C(A, B):
      pass
      print(C.__bases__)
      print(B.__subclasses__())
      """类名.__bases__: 可查看该类所有直接父类
      类名.__subclasses__():通过该方法可以查看该类的所有直接子类"""
      ########################3.枚举类
      """枚举的两种方式:
      (1)直接使用Enum列出多个枚举值来创建枚举类
      (2)通过继承Enum基类来派生枚举类
      """
      import enum
      Season = 'Season'
      Season = enum.Enum(Season, ('SPRING', 'SUMMER', 'FALL', 'WINTER'))
      print(Season.SPRING)
      print(Season.SPRING.name)
      print(Season.SPRING.value)
      print(Season['SUMMER'])
      print(Season(3))
      for name,member in Season.__members__.items():
       print(name,'=>',member,',',member.value)
      class Orientation(enum.Enum):
      #为序列值指定value值
       east = '东'
       south= '南'
       west = '西'
       north = '北'
      def info(self):
       print('这是一个代表方向【%s】的枚举' % self.value)
      print(Orientation.south)
      print(Orientation.south.value)
      print(Orientation['west'])
      print(Orientation('南'))
      print(Orientation.east.info())
      for name,member in Orientation.__members__.items():
       print(name,'=>',member,',',member.value)
      #枚举的构造器
      import  enum
      class Gender(enum.Enum):
       MALE = '男','阳刚之力'
       FEMALE = '女','柔顺之美'
      def __init__(self,cn_name,desc):
       self._cn_name = cn_name
       self._desc = desc
       @property
      def desc(self):
      return self._desc
       @property
      def cn_name(self):
      return self._cn_name
      print(Gender.FEMALE.name)
      print(Gender.FEMALE.value)
      print(Gender.FEMALE.cn_name)
      print(Gender.FEMALE.desc)
  
 

文章来源: blog.csdn.net,作者:血煞风雨城2018,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/qq_31905135/article/details/100554741

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。