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

举报
小米粒-biubiubiu 发表于 2020/11/29 00:27:33 2020/11/29
【摘要】 一、定义类,对象,实例方法和自动绑定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


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

二、方法


  
  1. class Bird:
  2. # 使用@Classmethod修饰的方法是类方法
  3. @classmethod
  4. def fly(cls):
  5. print('类方法fly:', cls)
  6. # 使用@staticmethod修饰的方法是静态方法
  7. @staticmethod
  8. def info(p):
  9. print('静态方法info:', p)
  10. Bird.fly()
  11. Bird.info("crazy")
  12. b = Bird()
  13. b.fly()
  14. b.info("kit")
  15. """前面的静态方法和类方法的本质就是函数装饰器,
  16. 其中classmethod和staticmethod都是python内置的函数"""
  17. def funA(fn):
  18. print('A')
  19. fn() # 执行传入的fn参数
  20. return 'end'
  21. @funA
  22. def funB():
  23. print('B')
  24. print(funB)
  25. """上面的程序@funA修饰funB,这意味着程序要完成两步操作
  26. 将funB作为funA()的参数,也就是上面的粗体字码相当于执行funA(funB)
  27. 将funB替换成第1步执行的结果,funA()执行完成后返回fkit,因此funB
  28. 就不再是函数,而是被替换成一个字符串
  29. """
  30. def foo(fn):
  31. # 定义一个嵌套函数
  32. def bar(*args):
  33. print("====1====", args)
  34. n = args[0]
  35. print('====2====', n * (n - 1))
  36. # 查看传给foo函数的fn函数
  37. print(fn.__name__)
  38. fn(n * (n - 1))
  39. print("*" * 15)
  40. return fn(n * (n - 1))
  41. return bar
  42. @foo
  43. def my_test(a):
  44. print('====my_test函数====', a)
  45. print(my_test)
  46. my_test(10)
  47. my_test(6, 5)
  48. # def auth(fn):
  49. # def auth_fn(*args):
  50. # print("模拟执行权限检查")
  51. # fn(*args)
  52. #
  53. # return auth_fn
  54. def auth(fn):
  55. def auth_fn(*args):
  56. print("模拟执行权限检查")
  57. fn(*args)
  58. return auth_fn
  59. @auth
  60. def test(a, b):
  61. print("asdasdasdasd啊实打实大苏打")
  62. test(20, 15)
  63. """上面介绍的这种在被修饰函数之前,之后,抛出异常后增加某种处理逻辑的方式
  64. 就是其他编程语言中的aop面向切面编程
  65. """
  66. class item:
  67. print('正在定义item类')
  68. for i in range(10):
  69. if i % 2 == 0:
  70. print('偶数',1)
  71. else:
  72. print('奇数',1)
  73. global_fn = lambda p:print('执行lambda表达式,p参数',p)
  74. class category:
  75. cate_fn = lambda p:print('执行lambda表达式,p参数',p)
  76. global_fn('fkit')
  77. c = category()
  78. c.cate_fn()

三、成员变量


  
  1. # 1.使用property函数定义属性
  2. class Rectangle:
  3. def __init__(self, width, height):
  4. self.width = width
  5. self.height = height
  6. def setSize(self, size):
  7. self.width, self.height = size
  8. def getSize(self):
  9. return self.width, self.height
  10. def delSize(self):
  11. self.width, self.height = 0, 0
  12. size = property(getSize, setSize, delSize, '用于描述矩形大小的属性')
  13. print(Rectangle.size.__doc__)
  14. help(Rectangle.size)
  15. rect = Rectangle(4, 3)
  16. # 相当于调用了getSize方法
  17. print(rect.size)
  18. rect.size = 9, 7
  19. print(rect.width)
  20. print(rect.height)
  21. # 删除size,相当于删除了width属性和height属性
  22. del rect.size
  23. print(rect.width)
  24. print(rect.height)
  25. """在某些编程语言中,类似于这种property合成的属性被称为计算属性。这种属性
  26. 并不真正存储任何状态,它的值其实是通过某种算法计算得到的,当程序对该属性赋值时,
  27. 被赋的值也会被存储到其他实例变量中
  28. """
  29. """还可以使用@property装饰器来修饰方法,使之成为属性"""
  30. class Cell:
  31. # 使用@property装饰器来修饰方法,相当于为该属性设置getter方法
  32. @property
  33. def state(self):
  34. return self._state
  35. # 为state属性设置setter方法
  36. @state.setter
  37. def state(self, value):
  38. if 'alive' in value.lower():
  39. self._state = 'alive'
  40. else:
  41. self._state = 'dead'
  42. # 为is_dead属性设置getter方法
  43. # 只有getter方法的属性是只读属性
  44. @property
  45. def is_dead(self):
  46. return not self._state.lower() == 'alive'
  47. c = Cell()
  48. c.state = 'Alive'
  49. print(c.state)
  50. print(c.is_dead)
  51. ##################隐藏和封装################
  52. class User:
  53. def __hide(self):
  54. print("示范隐藏的hide方法")
  55. def getname(self):
  56. return self.__name
  57. def setname(self, name):
  58. if len(name) < 3 or len(name) > 8:
  59. raise ValueError('用户名必须在3~8之间')
  60. self.__name = name
  61. name = property(getname,setname)
  62. u = User()
  63. #__hide其实是python悄悄修改了方法名,将__hide修改成了_类名__hide()
  64. u._User__hide()
  65. u._User__name = 'fk'
  66. print(u.name)
  67. """如果程序希望python类中的某些成员隐藏起来,那么只要让该成员的名字以双下划线开头即可。
  68. 即使通过这种机制实现了隐藏,其实也依然可以绕过去"""

四、类的继承


  
  1. # 1.类的继承
  2. class Fruit:
  3. def info(self):
  4. print('我是一个水果!重%g克' % self.weight)
  5. class Food:
  6. def taste(self):
  7. print("不同食物的口感不同")
  8. # 定义Apple类,继承了Fruit和Food类
  9. class Apple(Fruit, Food):
  10. pass
  11. a = Apple()
  12. a.weight = 5.6
  13. # 调用水果类的info方法
  14. a.info()
  15. # 调用食物类的taste方法
  16. a.taste()
  17. class Item:
  18. def info(self):
  19. print("item中方法:", '这是一个商品')
  20. class Product:
  21. def info(self):
  22. print("Product中方法:", "这是一个工业产品")
  23. class Mouse(Item, Product):
  24. pass
  25. m = Mouse()
  26. m.info()
  27. """Mouse继承了两个类,两个类具有相同的方法,但是Item排在Product的前面,
  28. 因此Item中定义的方法优先级更好,Python会优先到Item父类中搜寻方法,一旦
  29. 在Item父类中搜寻到目标方法,Python就不会继续向下搜寻了"""
  30. # 重写父类的方法
  31. class Bird:
  32. # Bird类的fly()方法
  33. def fly(self):
  34. print('我在天空里自由自在的飞翔')
  35. class Ostrich(Bird):
  36. def fly(self):
  37. print('我只能在地上奔跑')
  38. # 创建Ostrich
  39. os = Ostrich()
  40. # 执行子类的fly方法,将输出我只能在地上奔跑
  41. os.fly()
  42. class BaseClass:
  43. def foo(self):
  44. print('父类中定义的foo方法')
  45. class SubClass(BaseClass):
  46. def foo(self):
  47. print("子类重写父类中的foo方法")
  48. def bar(self):
  49. print('执行bar方法')
  50. self.foo()
  51. # 使用类名调用实例方法(未绑定方法)调用
  52. BaseClass.foo(self)
  53. sc = SubClass()
  54. sc.bar()
  55. # 使用super函数重写父类构造方法
  56. class Employee:
  57. def __init__(self, salary):
  58. self.salary = salary
  59. def work(self):
  60. print('普通员工正在写代码,工资是:', self.salary)
  61. class Customer:
  62. def __init__(self, favorite, address):
  63. self.favorite = favorite
  64. self.address = address
  65. def info(self):
  66. print('我是一个顾客,我的爱好是:%s,地址是: %s' % (self.favorite, self.address))
  67. class Manager(Employee,Customer):
  68. def __init__(self,salary,favorite,address):
  69. super(Manager,self).__init__(salary)
  70. Customer.__init__(self,favorite,address)
  71. m=Manager(25000,'it产品','广州')
  72. m.work()
  73. m.info()

五、python的动态性


  
  1. ############################################2.动态属性与_slots_
  2. #动态的给Cat类添加方法
  3. class Cat:
  4. def __init__(self,name):
  5. self.name = name
  6. def walk_func(self):
  7. print('%s 慢慢地走过一片草地' % self.name)
  8. d1 =Cat('Garfield')
  9. d2 =Cat('Kitty')
  10. Cat.walk = walk_func
  11. d1.walk()
  12. d2.walk()
  13. class Dog:
  14. __slots__ = ('walk','age','name','foo')
  15. def __init__(self,name):
  16. self.name = name
  17. def test(self):
  18. print('预先定义的test方法')
  19. d = Dog('snooy')
  20. #只允许为实例动态的添加walk,age,name这三个属性或者方法
  21. from types import MethodType
  22. d.walk = MethodType(lambda self:print('%s 正在慢慢的走'),d)
  23. d.age = 5
  24. d.walk()
  25. d.foo = 30
  26. #__slots__并不限制通过类来动态添加方法
  27. Dog.bar = lambda self: print('abc')
  28. d.bar()
  29. #####################3.使用type()函数定义类
  30. def fn(self):
  31. print("this is a 函数")
  32. Dog = type('Dog',(object,),dict(walk=fn,age=6))
  33. #创建Dog对象
  34. d = Dog()
  35. print(type(d))
  36. print(type(Dog))
  37. d.walk()
  38. print(Dog.age)
  39. """type定义类的时候可以指定三个参数
  40. 参数一:创建的类名
  41. 参数二:该类继承的父类集合,由于python 支持多继承,因此此处使用元组指定它的多个父类。即使实际
  42. 只有一个父类,也需要使用元组语法(必须要多一个逗号)
  43. 参数三:该字典对象为该类绑定的类变量和方法。其中字典key就是变量名或者方法名,
  44. 如果字典的value是普通值,那就代表类变量,如果字典的value是函数,则代表方法。
  45. """
  46. ###########################4.使用metaclass
  47. """如果希望创建某一批类全部具有某种特征,可通过metaclass来实现,使用metaclass可在创建类的
  48. 时候动态修改类定义,为了使用metaclass动态修改类定义,程序需要先定义metaclass,metaclass应该继承
  49. type类,并重写__new__()方法"""
  50. class ItemMetaclass(type):
  51. #cls代表被动态修改的类
  52. #name代表被动态修改的类名
  53. #bases代表被动态修改的类的所有父类
  54. #attr代表被动态修改的类的所有属性,方法组成的字典
  55. def __new__(cls, name,bases,attrs):
  56. attrs['cal_price'] = lambda self: self.price * self.discount
  57. return type.__new__(cls,name,bases,attrs)
  58. class Book(metaclass=ItemMetaclass):
  59. __slots__ = ('name','price','_discount')
  60. def __init__(self,name,price):
  61. self.name = name
  62. self.price = price
  63. @property
  64. def discount(self):
  65. return self._discount
  66. @discount.setter
  67. def discount(self,discount):
  68. self._discount = discount
  69. class CellPhone(metaclass=ItemMetaclass):
  70. __slots__ = ('price', '_discount')
  71. def __init__(self, price):
  72. self.price = price
  73. @property
  74. def discount(self):
  75. return self._discount
  76. @discount.setter
  77. def discount(self, discount):
  78. self._discount = discount
  79. """上面定义的Book类和CellPhone类都指定了metaclass信息,因此当
  80. python解释器在创建这两个类的时候,ItemMetaClass的__new__方法就会被调用,
  81. 用于修改这两个类,动态增加cal_price方法"""
  82. b= Book("疯狂python讲义",89)
  83. b.discount = 0.76
  84. print(b.cal_price())
  85. cp = CellPhone(2399)
  86. cp.discount = 0.85
  87. print(cp.cal_price())
  88. """metaclass这个功能在开发一些基础性框架时非常有用,程序可以通过
  89. 使用metaclass为某一批需要具有通用功能的类添加方法"""

六、多态


  
  1. #################1.多态性
  2. class Bird:
  3. def move(self, field):
  4. print('鸟在%s上自由的飞翔' % field)
  5. class Dog():
  6. def move(self, field):
  7. print('狗在%s里飞快地奔跑' % field)
  8. x = Bird()
  9. # 调用x变量
  10. x.move('天空')
  11. x = Dog()
  12. x.move('草地')
  13. class Canvas:
  14. def draw_pic(self, shape):
  15. print('---开始绘图---')
  16. shape.draw(self)
  17. class R:
  18. def draw(self, canvas):
  19. print('在%s上绘制矩形' % canvas)
  20. class T:
  21. def draw(self, canvas):
  22. print('在%s上绘制三角形' % Canvas)
  23. class Circle:
  24. def draw(self, canvas):
  25. print('在%s上h绘制圆形' % canvas)
  26. c = Canvas()
  27. c.draw_pic(R())
  28. c.draw_pic(T())
  29. #################2.检查类型
  30. """python提供了两个函数来检查类型
  31. issubclass(cls,class_or_tuple):检查cls是否是后一个类或者元组包含的多个类中任意类的子类
  32. isinstance(obj,class_or_tuple):检查obj是否是后一个类或者元组包含的多个类中任意类的对象
  33. 通过使用上面两个函数,程序可以方便地先执行检查,然后才调用方法,这样可以保证程序不会出现
  34. 意外情况
  35. """
  36. hello = "hello"
  37. print(isinstance(hello, str))
  38. print(issubclass(str, object))
  39. print(isinstance(hello, tuple))
  40. class A:
  41. pass
  42. class B:
  43. pass
  44. class C(A, B):
  45. pass
  46. print(C.__bases__)
  47. print(B.__subclasses__())
  48. """类名.__bases__: 可查看该类所有直接父类
  49. 类名.__subclasses__():通过该方法可以查看该类的所有直接子类"""
  50. ########################3.枚举类
  51. """枚举的两种方式:
  52. (1)直接使用Enum列出多个枚举值来创建枚举类
  53. (2)通过继承Enum基类来派生枚举类
  54. """
  55. import enum
  56. Season = 'Season'
  57. Season = enum.Enum(Season, ('SPRING', 'SUMMER', 'FALL', 'WINTER'))
  58. print(Season.SPRING)
  59. print(Season.SPRING.name)
  60. print(Season.SPRING.value)
  61. print(Season['SUMMER'])
  62. print(Season(3))
  63. for name,member in Season.__members__.items():
  64. print(name,'=>',member,',',member.value)
  65. class Orientation(enum.Enum):
  66. #为序列值指定value值
  67. east = '东'
  68. south= '南'
  69. west = '西'
  70. north = '北'
  71. def info(self):
  72. print('这是一个代表方向【%s】的枚举' % self.value)
  73. print(Orientation.south)
  74. print(Orientation.south.value)
  75. print(Orientation['west'])
  76. print(Orientation('南'))
  77. print(Orientation.east.info())
  78. for name,member in Orientation.__members__.items():
  79. print(name,'=>',member,',',member.value)
  80. #枚举的构造器
  81. import enum
  82. class Gender(enum.Enum):
  83. MALE = '男','阳刚之力'
  84. FEMALE = '女','柔顺之美'
  85. def __init__(self,cn_name,desc):
  86. self._cn_name = cn_name
  87. self._desc = desc
  88. @property
  89. def desc(self):
  90. return self._desc
  91. @property
  92. def cn_name(self):
  93. return self._cn_name
  94. print(Gender.FEMALE.name)
  95. print(Gender.FEMALE.value)
  96. print(Gender.FEMALE.cn_name)
  97. print(Gender.FEMALE.desc)

 

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

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

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

评论(0

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

全部回复

上滑加载中

设置昵称

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

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

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