我们在https://www.cnblogs.com/yinsedeyinse/p/9976280.html中学习了面向对象的编程方法。现在学习他的进阶用法。

1. 静态方法

2. 类方法

3. 属性方法

4. 类的特殊功能方法

静态方法、类方法以及属性方法:我们先定义一个类,在类里定义一个方法

  1. class Person(object):
  2. def __init__(self,name):
  3. self.name = name
  4.  
  5. def eat(self,food):
  6. print("%s is eating %s"%(self.name,food))
  7.  
  8. peaple = Person("Jack")
  9. peaple.eat("cake")
  1. Jack is eating cake

运行结果

这个是常规的类的使用,一切正常,

然后我们把方法前加一个@staticmethod,把eat()转变成一个静态方法,运行一下,程序报错了!

  1. TypeError: eat() missing 1 required positional argument: 'food'

运行结果

发现少了个参数,我们把程序简化一下,看看是怎么回事!

  1. class Person(object):
  2. def __init__(self,name):
  3. self.name = name
  4. self.__food = None
  5. @staticmethod
  6. def eat(self):
  7. print(self.name)
  8. peaple = Person("Jack")
  9. peaple.eat()
  1. TypeError: eat() missing 1 required positional argument: 'self'

运行结果

再改一下

  1. class Person(object):
  2. def __init__(self,name):
  3. self.name = name
  4. self.__food = None
  5. @staticmethod
  6. def eat(name,food):
  7. print("%s is eating %s"%(name,food))
  8. peaple = Person("Jack")
  9. peaple.eat("David","cake")
  1. David is eating cake

运行结果

可以发现,静态方法无法调用类里的属性了!

所以,静态方法就是实际上已经跟类没什么关系了,也就是名义上归类管理。在方法内无法调用类或实例里的任何属性。还有个用法相当于类的工具包(高级语法,有机会再说!)。

我们再看看类方法,在方法前加上@classmethod运行一下

  1. class Person(object):
  2. def __init__(self,name):
  3. self.name = name
  4. @classmethod #类方法
  5. def eat(self,food):
  6. print("%s is eating %s"%(self.name,food))
  7. peaple = Person("Jack")
  8. peaple.eat("cake")
  1. AttributeError: type object 'Person' has no attribute 'name'

运行结果

提示没有“name”的变量,为什么呢?我们把name定义成类变量试一试。

  1. class Person(object):
  2. name = "Jeff"
  3. def __init__(self,name):
  4. self.name = name
  5. @classmethod
  6. def eat(self,food):
  7. print("%s is eating %s"%(self.name,food))
  8. peaple = Person("Jack")
  9. peaple.eat("cake")
  1. Jeff is eating cake

运行结果

类变量只能访问类变量,不能访问实例变量。

属性方法

  1. class Person(object):
  2. def __init__(self,name):
  3. self.name = name
  4. @property
  5. def eat(self):
  6. print("%s is eating"%self.name)
  7. p1 = Person("Jack")
  8. p1.eat #这里的p1.eat调用的是属性,不是方法
  1. Jack is eating

运行结果

在这个方法前加了@property,就把原来的方法改成了属性方法。在实例化后,不能用访问方法的形式(p1.eat())去访问,而要用属性的形式(p1.eat)。

但是有个问题,如果在属性方法里有参数需要传递的话,就要用到装饰器了!

  1. class Person(object):
  2. def __init__(self,name):
  3. self.name = name
  4. self.__food = None #先定义个私有属性
  5. @property
  6. def eat(self):
  7. print("%s is eating %s"%(self.name,self.__food))
  8. @eat.setter #定义装饰器
  9. def eat(self,food):
  10. print("set to food:",food)
  11. self.__food = food
  12. p1 = Person("Jack")
  13. p1.eat
  14. p1.eat = "bread" #对属性方法赋值
  15. p1.eat
  1. Jack is eating None
  2. set to food: bread
  3. Jack is eating bread

运行结果

完成效果,如果我们想把属性方法删除,用一般的删除方法是不行的

  1. del p1.eat

这时候我们必须在类里重新定义个方法

  1. class Person(object):
  2. def __init__(self,name):
  3. self.name = name
  4. self.__food = None #先定义个私有属性
  5. @property
  6. def eat(self):
  7. print("%s is eating %s"%(self.name,self.__food))
  8. @eat.setter #定义装饰器
  9. def eat(self,food):
  10. print("set to food:",food)
  11. self.__food = food
  12. @eat.deleter #删除方法
  13. def eat(self):
  14. del self.__food
  15. print("已删除!")
  16. p1 = Person("Jack")
  17. p1.eat
  18. p1.eat = "bread" #对属性方法赋值
  19. p1.eat
  20. del p1.eat #删除属性方法
  21. p1.eat #重新调用测试一下
  1. Jack is eating None
  2. set to food: bread
  3. Jack is eating bread
  4. 已删除!
  5. Traceback (most recent call last):
  6. File "D:/python/week7/属性方法.py", line 45, in <module>
  7. p1.eat
  8. File "D:/python/week7/属性方法.py", line 31, in eat
  9. print("%s is eating %s"%(self.name,self.__food))
  10. AttributeError: 'Person' object has no attribute '_Person__food'

运行结果

那有什么用呢?几个例子,航空公司都能提供航班状态,而其他的三方运营商需要调用这个值,显而易见的是运营商不能修改航班状态

  1. class Flight(object):
  2. def __init__(self,name):
  3. self.name = name
  4.  
  5. def checking_status(self):
  6. print("checking flight %s status"%self.name)
  7. @property
  8. def flight_status(self):
  9. status = self.checking_status()
  10. if status == 0:
  11. print("flight is caceled!")
  12. elif status == 1:
  13. print("flight is arrived!")
  14. elif status == 2:
  15. print("flight has departured already!")
  16. else:
  17. print("cannot confirm the flight status,please check later!")
  18.  
  19. @flight_status.setter #航空公司返回航班的状态关键字
  20. def flight_status(self,status):
  21. status_dic = {
  22. 0:'caceled',
  23. 1:'arrived',
  24. 2:'departured'
  25. }
  26.  
  27. @flight_status.deleter #删除该航班状态
  28. def flight_status(self):
  29. print("status is deleted!")
  30. f = Flight("MU2388") #要查的航班编号
  31. f.flight_status = 1 #航空公司每次只返回一个值描述出该航班状态
  32. f.flight_status #其他的运营商直接访问属性的值,而不能改变其状态 

现在来看一看一些类的特殊方法:

1.__doc__  获取类的描述信息

  1. # Author:Aaron
  2. class People():
  3. '''
  4. 该类描述了人类
  5. '''
  6. def func1(self):
  7. pass
  8. print(People.__doc__)
  1. C:\Users\Aaron\Anaconda3\python.exe D:/python/week7/类的特殊成员.py
  2. 该类描述了人类

运行结果

在对类进行描述时,只能用‘’‘——’‘’来注释,用#注释时返回值为None。并且__doc__可以在不进行实例化时直接对类使用,也可以对实例使用。

2.__module__和__class__

  1. from lib.aa import C
  2. obj = C()
  3. print(obj.__module__) #输出lib.aa,即为输出该功能所属模块
  4. print(obj.__class__) #输出lib.aa.C,即为输出该类

在大量调用模块时,用这两个方法可以显示调用的类是属于那个模块的。

3.__call__

在实例后加(),执行功能

  1. class Dog():
  2. def __call__(self, *args, **kwargs):
  3. print("__call__的用法")
  4. d1 = Dog()
  5. d1()
  1. C:\Users\Aaron\Anaconda3\python.exe D:/python/week7/类的特殊成员.py
  2. __call__的用法

运行结果

在功能中,可以传递各种参数。

4.__dict__查看类或对象中的所有成员

  1. class People():
  2. def __init__(self,name,age,sex):
  3. self.name = name
  4. self.age = age
  5. self.sex = sex
  6. def eat(self):
  7. pass
  8. def talk(self):
  9. pass
  10.  
  11. p1= People("Jack",22,"male")
  12. print(p1.__dict__) #打印所有实例属性,不包括类属性
  13. print(People.__dict__) #打印所有类属性,不包括实例属性
  1. C:\Users\Aaron\Anaconda3\python.exe D:/python/week7/类的特殊成员.py
  2. {'name': 'Jack', 'age': 22, 'sex': 'male'}
  3. {'__module__': '__main__', '__init__': <function People.__init__ at 0x00000243C1246510>, 'eat': <function People.eat at 0x00000243C1246598>, 'talk': <function People.talk at 0x00000243C1246620>, '__dict__': <attribute '__dict__' of 'People' objects>, '__weakref__': <attribute '__weakref__' of 'People' objects>, '__doc__': None}

运行结果

以一个字典的形式把类或实例的方法打印出来,作用是在程序运行以后,如果有新加的属性,可以用这个方式查看。

 5.__str__   可以直接用print打印字符串

  1. class People():
  2. def __init__(self,name):
  3. self.name = name
  4. def __str__(self):
  5. return 'obj:%s'%self.name
  6.  
  7. p = People('Jeck')
  8. print(p)
  1. C:\Users\Aaron\Anaconda3\python.exe D:/python/week7/类的特殊成员.py
  2. obj:Jeck

运行结果

django中常用的用法,可以用来返回实例。

6. __getitem__,__setitem__,__delitem__

可以把一个字典封装成一个实例(类),用字典的方式添加类的属性等。然后控制字典的权限。用户可以访问这个字典其实是访问了一个类,但可以对用户进行权限控制。

Python 面向对象编程之进阶使用的更多相关文章

  1. python面向对象编程之组合

    前面讲了面向类与对象的继承,知道了继承是一种什么"是"什么的关系. 然而类与类之间还有另一种关系,这就是组合 先来看两个例子: 先定义两个类,一个老师类,老师类有名字,年龄,出生的 ...

  2. Python 面向对象编程之封装的艺术

    1. 面向对象编程 OOP ( Object  Oriented Programming) 即面向对象编程. 面向对象编程是一种编码思想,或是一种代码组织方式.如同编辑文章时,可以选择分段.分节的方式 ...

  3. python基础-面向对象编程之继承

    面向对象编程之继承 继承的定义:是一种新建类的方式,新建的类称之为子类或派生类,被继承的父类称之为基类或超类 继承的作用:子类会""遗传"父类的属性,从而解决代码重用问题 ...

  4. python基础-面向对象编程之封装、访问限制机制和property

    面向对象编程之封装 封装 定义:将属性和方法一股脑的封装到对象中,使对象可通过"对象."的方式获取或存储数据. 作用:让对象有了"."的机制,存取数据更加方便 ...

  5. python基础-面向对象编程之反射

    面向对象编程之反射 反射 定义:通过字符串对对象的属性和方法进行操作. 反射有4个方法,都是python内置的,分别是: hasattr(obj,name:str) 通过"字符串" ...

  6. python基础-面向对象编程之多态

    面向对象编程之多态以及继承.抽象类和鸭子类型三种表现形式 多态 定义:同一种类型的事物,不同的形态 作用: 多态也称之为"多态性".用于在不知道对象具体类型的情况下,统一对象调用方 ...

  7. python基础-面向对象编程之组合

    面向对象编程之组合 定义:一个对象中拥有另一个或其他多个对象的属性和方法. 作用:减少代码的冗余,降低耦合度 关于耦合度的说明 耦合:通俗地讲,就是相互作用,相互影响的意思 耦合度越高,程序的可扩展性 ...

  8. Python编程之美:最佳实践指南PDF高清完整版免费下载|百度云盘|Python新手到进阶

    百度云盘:Python编程之美:最佳实践指南PDF高清完整版免费下载 提取码:1py6 内容简介 <Python编程之美:最佳实践指南>是Python用户的一本百科式学习指南,由Pytho ...

  9. 深入理解JavaScript系列(17):面向对象编程之概论

    介绍 在本篇文章,我们考虑在ECMAScript中的面向对象编程的各个方面(虽然以前在许多文章中已经讨论过这个话题).我们将更多地从理论方面看这些问题. 特别是,我们会考虑对象的创建算法,对象(包括基 ...

随机推荐

  1. ubuntu 安汉google浏览器

    在终端中,输入以下命令: sudo wget https://repo.fdzh.org/chrome/google-chrome.list -P /etc/apt/sources.list.d/   ...

  2. 转:C语言inline详细讲解

    本文介绍了GCC和C99标准中inline使用上的不同之处.inline属性在使用的时候,要注意以下两点:inline关键字在GCC参考文档中仅有对其使用在函数定义(Definition)上的描述,而 ...

  3. Django学习之序列化和信号

    一.序列化 1.serializers 2.json.dumps 二.信号 1.Django内置信号 2.自定义信号 一.序列化 关于Django中的序列化主要应用在将数据库中检索的数据返回给客户端用 ...

  4. Python学习之==>面向对象编程(一)

    一.面向对象与面向过程 面向对象与面向过程是两种不同的编程范式,范式指的是按照什么方式去编程.去实现一个功能.不同的编程范式本质上代表对各种不同类型的任务采取不同的解决问题的思路. 1.面向过程编程 ...

  5. Linux mysql ERROR 1045 解决

    Linux mysql 5.6: ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) ...

  6. 打印GC日志

    所需参数如下: -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -verbose:gc -Xloggc:gc.log 会在根目录生成 gc.log 文件,里面记录 ...

  7. 【ABAP系列】SAP 系统的消息类型分析 MESSAGE TYPE

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP 系统的消息类型分析 ME ...

  8. LeetCode算法题-Positions of Large Groups(Java实现)

    这是悦乐书的第323次更新,第346篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第193题(顺位题号是830).在由小写字母组成的字符串S中,那些相同的连续字符会组成集 ...

  9. 操作系统(3)实验相关原理——bootloader启动uCore

    x86启动顺序 CS+EIP决定启动地址. CS部分后面又4个0,相当于是左移了4位.总之就是要让CS左移4位之后加上EIP来得到要跳转的地址. 0x7c00地方开始的512字节的内容就是bootlo ...

  10. java中线程同步的理解(非常通俗易懂)

    转载至:https://blog.csdn.net/u012179540/article/details/40685207 Java中线程同步的理解 我们可以在计算机上运行各种计算机软件程序.每一个运 ...