本节内容:

  • 面向对象高级语法部分

    • 经典类vs新式类  
    • 静态方法、类方法、属性方法
    • 类的特殊方法
    • 反射
  • 异常处理
  • Socket开发基础
  • 作业:开发一个支持多用户在线的FTP程序

  

面向对象高级语法部分

经典类vs新式类

把下面代码用python2 和python3都执行一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#_*_coding:utf-8_*_
 
 
class A:
    def __init__(self):
        self.n = 'A'
 
class B(A):
    # def __init__(self):
    #     self.n = 'B'
    pass
 
class C(A):
    def __init__(self):
        self.n = 'C'
 
class D(B,C):
    # def __init__(self):
    #     self.n = 'D'
    pass
 
obj = D()
 
print(obj.n)

classical vs new style:

  • 经典类:深度优先
  • 新式类:广度优先
  • super()用法

抽象接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import abc
 
class Alert(object):
    '''报警基类'''
    __metaclass__ = abc.ABCMeta
 
    @abc.abstractmethod
    def send(self):
        '''报警消息发送接口'''
        pass
 
 
 
class MailAlert(Alert):
    pass
 
 
= MailAlert()
m.send()

上面的代码仅在py2里有效,python3里怎么实现呢?

  

  

静态方法

通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法,什么是静态方法呢?其实不难理解,普通的方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量,但静态方法是不可以访问实例变量或类变量的,一个不能访问实例变量和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法

1
2
3
4
5
6
7
8
9
10
11
12
13
class Dog(object):
 
    def __init__(self,name):
        self.name = name
 
    @staticmethod #把eat方法变为静态方法
    def eat(self):
        print("%s is eating" % self.name)
 
 
 
= Dog("ChenRonghua")
d.eat()

上面的调用会出以下错误,说是eat需要一个self参数,但调用时却没有传递,没错,当eat变成静态方法后,再通过实例调用时就不会自动把实例本身当作一个参数传给self了。

1
2
3
4
Traceback (most recent call last):
  File "/Users/jieli/PycharmProjects/python基础/自动化day7面向对象高级/静态方法.py", line 17in <module>
    d.eat()
TypeError: eat() missing 1 required positional argument: 'self'

想让上面的代码可以正常工作有两种办法

1. 调用时主动传递实例本身给eat方法,即d.eat(d)

2. 在eat方法中去掉self参数,但这也意味着,在eat中不能通过self.调用实例中的其它变量了

 1 class Dog(object):
2
3 def __init__(self,name):
4 self.name = name
5
6 @staticmethod
7 def eat():
8 print(" is eating")
9
10
11
12 d = Dog("ChenRonghua")
13 d.eat()

类方法  

类方法通过@classmethod装饰器实现,类方法和普通方法的区别是, 类方法只能访问类变量,不能访问实例变量

1
2
3
4
5
6
7
8
9
10
11
12
class Dog(object):
    def __init__(self,name):
        self.name = name
 
    @classmethod
    def eat(self):
        print("%s is eating" % self.name)
 
 
 
= Dog("ChenRonghua")
d.eat()

执行报错如下,说Dog没有name属性,因为name是个实例变量,类方法是不能访问实例变量的

1
2
3
4
5
6
Traceback (most recent call last):
  File "/Users/jieli/PycharmProjects/python基础/自动化day7面向对象高级/类方法.py", line 16in <module>
    d.eat()
  File "/Users/jieli/PycharmProjects/python基础/自动化day7面向对象高级/类方法.py", line 11in eat
    print("%s is eating" % self.name)
AttributeError: type object 'Dog' has no attribute 'name'

此时可以定义一个类变量,也叫name,看下执行效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Dog(object):
    name = "我是类变量"
    def __init__(self,name):
        self.name = name
 
    @classmethod
    def eat(self):
        print("%s is eating" % self.name)
 
 
 
= Dog("ChenRonghua")
d.eat()
 
 
#执行结果
 
我是类变量 is eating

属性方法  

属性方法的作用就是通过@property把一个方法变成一个静态属性

1
2
3
4
5
6
7
8
9
10
11
12
class Dog(object):
 
    def __init__(self,name):
        self.name = name
 
    @property
    def eat(self):
        print(" %s is eating" %self.name)
 
 
= Dog("ChenRonghua")
d.eat()

调用会出以下错误, 说NoneType is not callable, 因为eat此时已经变成一个静态属性了, 不是方法了, 想调用已经不需要加()号了,直接d.eat就可以了

1
2
3
4
5
Traceback (most recent call last):
 ChenRonghua is eating
  File "/Users/jieli/PycharmProjects/python基础/自动化day7面向对象高级/属性方法.py", line 16in <module>
    d.eat()
TypeError: 'NoneType' object is not callable

正常调用如下

1
2
3
4
5
= Dog("ChenRonghua")
d.eat
 
输出
 ChenRonghua is eating

好吧,把一个方法变成静态属性有什么卵用呢?既然想要静态变量,那直接定义成一个静态变量不就得了么?well, 以后你会需到很多场景是不能简单通过 定义 静态属性来实现的, 比如 ,你想知道一个航班当前的状态,是到达了、延迟了、取消了、还是已经飞走了, 想知道这种状态你必须经历以下几步:

1. 连接航空公司API查询

2. 对查询结果进行解析

3. 返回结果给你的用户

因此这个status属性的值是一系列动作后才得到的结果,所以你每次调用时,其实它都要经过一系列的动作才返回你结果,但这些动作过程不需要用户关心, 用户只需要调用这个属性就可以,明白 了么?

 航班查询

cool , 那现在我只能查询航班状态, 既然这个flight_status已经是个属性了, 那我能否给它赋值呢?试试吧

1
2
3
= Flight("CA980")
f.flight_status
f.flight_status =  2

输出, 说不能更改这个属性,我擦。。。。,怎么办怎么办。。。

1
2
3
4
5
6
checking flight CA980 status
flight is arrived...
Traceback (most recent call last):
  File "/Users/jieli/PycharmProjects/python基础/自动化day7面向对象高级/属性方法.py", line 58in <module>
    f.flight_status =  2
AttributeError: can't set attribute

当然可以改, 不过需要通过@proerty.setter装饰器再装饰一下,此时 你需要写一个新方法, 对这个flight_status进行更改。

 

注意以上代码里还写了一个@flight_status.deleter, 是允许可以将这个属性删除

类的特殊成员方法

1. __doc__  表示类的描述信息

1
2
3
4
5
6
7
8
class Foo:
    """ 描述类信息,这是用于看片的神奇 """
 
    def func(self):
        pass
 
print Foo.__doc__
#输出:类的描述信息

2. __module__ 和  __class__ 

  __module__ 表示当前操作的对象在那个模块

  __class__     表示当前操作的对象的类是什么

class C:

    def __init__(self):
self.name = 'wupeiqi'
from lib.aa import C

obj = C()
print obj.__module__ # 输出 lib.aa,即:输出模块
print obj.__class__ # 输出 lib.aa.C,即:输出类

3. __init__ 构造方法,通过类创建对象时,自动触发执行。

4.__del__

 析构方法,当对象在内存中被释放时,自动触发执行。

注:此方法一般无须定义,因为Python是一门高级语言,程序员在使用时无需关心内存的分配和释放,因为此工作都是交给Python解释器来执行,所以,析构函数的调用是由解释器在进行垃圾回收时自动触发执行的

  

5. __call__ 对象后面加括号,触发执行。

注:构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()()

1
2
3
4
5
6
7
8
9
10
11
12
class Foo:
 
    def __init__(self):
        pass
     
    def __call__(self*args, **kwargs):
 
        print '__call__'
 
 
obj = Foo() # 执行 __init__
obj()       # 执行 __call__

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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__
# 输出:{'country': 'China', '__module__': '__main__', 'func': <function func at 0x10be30f50>, '__init__': <function __init__ at 0x10be30ed8>, '__doc__': None}
 
obj1 = Province('HeBei',10000)
print obj1.__dict__
# 获取 对象obj1 的成员
# 输出:{'count': 10000, 'name': 'HeBei'}
 
obj2 = Province('HeNan'3888)
print obj2.__dict__
# 获取 对象obj1 的成员
# 输出:{'count': 3888, 'name': 'HeNan'}

7.__str__ 如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。

1
2
3
4
5
6
7
8
9
class Foo:
 
    def __str__(self):
        return 'alex li'
 
 
obj = Foo()
print obj
# 输出:alex li

8.__getitem__、__setitem__、__delitem__

用于索引操作,如字典。以上分别表示获取、设置、删除数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Foo(object):
 
    def __getitem__(self, key):
        print('__getitem__',key)
 
    def __setitem__(self, key, value):
        print('__setitem__',key,value)
 
    def __delitem__(self, key):
        print('__delitem__',key)
 
 
obj = Foo()
 
result = obj['k1']      # 自动触发执行 __getitem__
obj['k2'= 'alex'   # 自动触发执行 __setitem__
del obj['k1']   

9. __new__ \ __metaclass__

1
2
3
4
5
6
7
8
class Foo(object):
 
 
    def __init__(self,name):
        self.name = name
 
 
= Foo("alex")

上述代码中,obj 是通过 Foo 类实例化的对象,其实,不仅 obj 是一个对象,Foo类本身也是一个对象,因为在Python中一切事物都是对象

如果按照一切事物都是对象的理论:obj对象是通过执行Foo类的构造方法创建,那么Foo类对象应该也是通过执行某个类的 构造方法 创建。

1
2
print type(f) # 输出:<class '__main__.Foo'>     表示,obj 对象由Foo类创建
print type(Foo) # 输出:<type 'type'>              表示,Foo类对象由 type 类创建

所以,f对象是Foo类的一个实例Foo类对象是 type 类的一个实例,即:Foo类对象 是通过type类的构造方法创建。

那么,创建类就可以有两种方式:

a). 普通方式

1
2
3
4
class Foo(object):
  
    def func(self):
        print 'hello alex'

b). 特殊方式

1
2
3
4
5
6
7
def func(self):
    print 'hello wupeiqi'
  
Foo = type('Foo',(object,), {'func': func})
#type第一个参数:类名
#type第二个参数:当前类的基类
#type第三个参数:类的成员
def func(self):
print("hello %s"%self.name) def __init__(self,name,age):
self.name = name
self.age = age
Foo = type('Foo',(object,),{'func':func,'__init__':__init__}) f = Foo("jack",22)
f.func()

So ,孩子记住,类 是由 type 类实例化产生

那么问题来了,类默认是由 type 类实例化产生,type类中如何实现的创建类?类又是如何创建对象?

答:类中有一个属性 __metaclass__,其用来表示该类由 谁 来实例化创建,所以,我们可以为 __metaclass__ 设置一个type类的派生类,从而查看 类 创建的过程。

 1 class MyType(type):
2 def __init__(self,*args,**kwargs):
3
4 print("Mytype __init__",*args,**kwargs)
5
6 def __call__(self, *args, **kwargs):
7 print("Mytype __call__", *args, **kwargs)
8 obj = self.__new__(self)
9 print("obj ",obj,*args, **kwargs)
10 print(self)
11 self.__init__(obj,*args, **kwargs)
12 return obj
13
14 def __new__(cls, *args, **kwargs):
15 print("Mytype __new__",*args,**kwargs)
16 return type.__new__(cls, *args, **kwargs)
17
18 print('here...')
19 class Foo(object,metaclass=MyType):
20
21
22 def __init__(self,name):
23 self.name = name
24
25 print("Foo __init__")
26
27 def __new__(cls, *args, **kwargs):
28 print("Foo __new__",cls, *args, **kwargs)
29 return object.__new__(cls)
30
31 f = Foo("Alex")
32 print("f",f)
33 print("fname",f.name)

类的生成 调用 顺序依次是 __new__ --> __init__ --> __call__

metaclass 详解文章:http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python 得票最高那个答案写的非常好

反射

通过字符串映射或修改程序运行时的状态、属性、方法, 有以下4个方法

def getattr(object, name, default=None): # known special case of getattr
"""
getattr(object, name[, default]) -> value Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
When a default argument is given, it is returned when the attribute doesn't
exist; without it, an exception is raised in that case.
"""
pass
判断object中有没有一个name字符串对应的方法或属性
def setattr(x, y, v): # real signature unknown; restored from __doc__
"""
Sets the named attribute on the given object to the specified value. setattr(x, 'y', v) is equivalent to ``x.y = v''
def delattr(x, y): # real signature unknown; restored from __doc__
"""
Deletes the named attribute from the given object. delattr(x, 'y') is equivalent to ``del x.y''
"""
class Foo(object):

    def __init__(self):
self.name = 'wupeiqi' def func(self):
return 'func' obj = Foo() # #### 检查是否含有成员 ####
hasattr(obj, 'name')
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
2
3
4
import importlib
 
__import__('import_lib.metaclass'#这是解释器自己内部用的
#importlib.import_module('import_lib.metaclass') #与上面这句效果一样,官方建议用这个

  

异常处理

参考 http://www.cnblogs.com/wupeiqi/articles/5017742.html

Socket 编程

参考:http://www.cnblogs.com/wupeiqi/articles/5040823.html

Python基础7 面向对象编程进阶的更多相关文章

  1. Day7 - Python基础7 面向对象编程进阶

    Python之路,Day7 - 面向对象编程进阶   本节内容: 面向对象高级语法部分 经典类vs新式类 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 作业:开发一个 ...

  2. Python基础-week06 面向对象编程进阶

    一.反射 1.定义:指的是通过字符串来操作类或者对象的属性 2.为什么用反射? 减少冗余代码,提升代码质量. 3.如何用反射? class People: country='China' def __ ...

  3. Python基础之面向对象编程

    面向对象编程 —— Object Oriented Programming 简写 OOP 01. 面向对象基本概念 我们之前学习的编程方式就是 面向过程 的 面向过程 和 面向对象,是两种不同的 编程 ...

  4. Day6 - Python基础6 面向对象编程

    Python之路,Day6 - 面向对象学习   本节内容:   面向对象编程介绍 为什么要用面向对象进行开发? 面向对象的特性:封装.继承.多态 类.方法.     引子 你现在是一家游戏公司的开发 ...

  5. Python基础6 面向对象编程

    本节内容:   面向对象编程介绍 为什么要用面向对象进行开发? 面向对象的特性:封装.继承.多态 类.方法.     引子 你现在是一家游戏公司的开发人员,现在需要你开发一款叫做<人狗大战> ...

  6. python基础之面向对象编程介绍、类和对象

    面向对象变成介绍 面向过程编程 核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西.主要应用在一旦完成很少修改的地方,如linux ...

  7. Python基础-week06 面向对象编程基础

    一.面向对象编程 1.面向过程 与 面向对象编程 面向过程的程序设计: 核心是 过程二字,过程指的是解决问题的步骤,即先干什么再干什么......面向过程的设计就好比精心设计好一条流水线,是一种机械式 ...

  8. Python基础之面向对象(进阶篇)

    面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个“函数”供使用(可以讲多函数中公用的变量封装到对象中) 对象,根据模板创建的实例(即:对象),实 ...

  9. Python基础——6面向对象编程

    类和实例 类是抽象的模版,例如汽车:而实例则是拥有相同方法的类的实现,例如汽车里面有大众.宝马.奔驰等等,这些车都能在地面上跑,但是它们的具体数据可以不一样. calss Student(object ...

随机推荐

  1. 简单说throw和throws的区别

    1. 区别 throws是用来声明一个方法可能抛出的所有异常信息,throws是将异常声明但是不处理,而是将异常往上传,谁调用我就交给谁处理.而throw则是指抛出的一个具体的异常类型. 2.分别介绍 ...

  2. 黄聪:bootstrap中模态框modal在苹果手机上会失效

    bootstrap中模态框在苹果手机上会失效 可将代码修改为<a  data-toggle="modal" data-target="#wrap" hre ...

  3. Android兼容包之MultiDex

    一.MultiDex的产生背景 当Android系统安装一个应用的时候,有一步是对Dex进行优化,这个过程有一个专门的工具来处理,叫DexOpt.DexOpt的执行过程是在第一次加载Dex文件的时候执 ...

  4. Svn过滤

    http://blog.csdn.net/hemingwang0902/article/details/6904205

  5. ubuntu16.04 彻底卸载MySQL

    以MySQL- 5.7.18为例: sudo apt-get autoremove --purge mysql-server-5.7 #sudo apt-get remove mysql-server ...

  6. LinkedList的自定义实现

    一.背景 LinkedList双向链表: 代码: Node.java: package com.cy.collection; public class Node { Node previous; // ...

  7. react事件中的this指向

    在react中绑定事件处理函数的this指向一共有三种方法,本次主要总结这三种方式. 项目创建 关于项目的创建方法,在之前的文章中有记录,这里不再赘述,项目创建成功后,按照之前的目录结构对生成的项目进 ...

  8. 项目中自己一直用到的baseAdapter的类

    import java.util.LinkedList; import java.util.List; import android.content.Context; import android.v ...

  9. github webhook 实现代码自动部署 踩坑!! 附加git&coding webhook部署代码

    踩坑: 1.php程序执行linux命令是以webserver的user用户(如apache .www……)操作的,需要在/etc/sudoers添加用户免密码操作权限; %apache ALL=(A ...

  10. 常用docker镜像

    oracle12c: mkdir -p /path/to/oradata docker run --name oracle12c \ -p 1521:1521 -p 5500:5500 \ -v /p ...