面向对象进阶

成员:

类的成员可以分为三大类:字段、方法和属性

注:所有成员中,只有普通字段的内容保存对象中,即:根据此类创建了多少对象,在内存中就有多少个普通字段。而其他的成员,则都是保存在类中,即:无论对象的多少,在内存中只创建一份。

一、字段

字段包括:普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同,

  • 普通字段属于对象
  • 静态字段属于
class Foo:
    def __init__(self,name):
        #普通字段 保存在对象中
        self.name = name
        #普通方法  保存在类中
    def shou(self):
        print('sssssssss')
f1 = Foo('开始')
print(f1.name)
f1.shou()

执行结果
开始
sssssssss
字段的定义和使用
class provice:
    country = '中国'
    def __init__(self,name):
        self.name = name
    def shou(self):
        self.name = self.name
print(provice.country)
shanxi = provice('山西')

执行结果:
中国
山西
静态字段

静态字段:自己的成员自己访问,除了类中的方法 类中的方法不不要让类访问

由上述代码可以看出【普通字段需要通过对象来访问】【静态字段通过类访问】,在使用上可以看出普通字段和静态字段的归属是不同的 其在内容的存储方式类似如下图:

由上图可是:

  • 静态字段在内存中只保存一份
  • 普通字段在每个对象中都要保存一份

应用场景: 通过类创建对象时,如果每个对象都具有相同的字段,那么就使用静态字段

方法:

方法包括:普通方法,静态方法,和类方法,三种方法都在内存总归属于类,区别在于调用的方式不同

普通方法:
class TXX:
    def __init__(self,name):
        self.name = name
    def fang(self):                   #定义普通方法,至少要有一个self擦数
        print('普通方法sss')
tt = TXX(1)
tt.fang()

类方法:
class Txx:   # 类方法      通过class 将类名传进去
    def __init__(self,name):
        self.name = name
    @classmethod 
    def XXoo(cls):            定义类方法的时候,至少要有一个cls 参数
        print('xxxxxxx',cls)
Txx.XXoo()


class Txx:
    def  __init__(self,name):
        self.name = name
    @staticmethod    #静态方法
    def xoo():                          定义静态方法,无默认的参数
        print('静态方法ssssss')
Txx.xoo()
方法定义和使用

相同点:对于所有的方法而言,均属于类(非对象)中,所以,在内存中也只保存一份。

不同点:方法调用者不同、调用方法时自动传入的参数不同。

特性属性:

1.普通特性:为了把方法伪装成字段的形式来访问

a.@property将类中原来的方法伪装成字段的方法去获取

b.@end.setter设置对应特性方法的值

c.在使用特性后的方法不可以添加参数了

class Foo:
    def __init__(self,name):
        self.name = name
     #特性,讲方法伪造成一种字段
    @property           #获取特性
    def end(self):
        temp = "%s sb"%self.name
        return temp

    @end.setter         # 设置特性
    def end(self,val):
         print(val)
         self.name = val

obj = Foo('sssss')
print(obj.end)
obj.end = 'zzzz'
print(obj.end)
属性的定义和使用

4, 对于成员的访问与调用:

通过对象访问的 有两种 普通字段,类的方法

通过类访问的 静态字段,静态方法

对于有self参数的就是类调用  

没有self参数的就是对象调用

特性的两种方式定义:

属性的定义有两种方式:

  • 装饰器 即:在方法上应用装饰器
  • 静态字段 即:在类中定义值为property对象的静态字段段

装饰器方式:

在类的普通方法上应用@property装饰器

经典类,具有一种@property装饰器

#!/usr/bin/env/python
# -*- coding:utf-8 -*-

class FOO:
    def func(self):
        print('aaaa')
    @property
    def pp(self):
        print('方法一')
        return 1111
obj = FOO()       
obj.func()
ret = obj.pp      自动执行 @property 修饰的pp方法 并获取回返回值
print(ret)
经典类
class Fooo:
    def func(self):
        print('鼠疫')
    @property
    def pp(self):
        print('方法一')
        return 1111

    @pp.setter
    def pp(self,value):
        print(value)

    @pp.deleter
    def pp(self):
        print('del')

obj = Fooo()
obj.func()
print(obj.pp)    自动执行 @property 修饰的 pp方法,并获取方法的返回值
obj.pp = 999     自动执行 @price.setter 修饰的 pp 方法,并将  999赋值给方法的参数
del obj.pp      # 自动执行 @price.deleter 修饰的 pp方法
新式类,三种@property装饰器

静态字段方式,创建值为property对象的静态字段

当使用静态字段的方式创建属性时,经典类和新式类无区别

class FOO:
    def get(self):
        return '1111'
    ss = property(get)
obj = FOO()
s = obj.ss
print(s)
经典类

property的构造方法中有个四个参数

  • 第一个参数是方法名,调用 对象.属性 时自动触发执行方法
  • 第二个参数是方法名,调用 对象.属性 = XXX 时自动触发执行方法
  • 第三个参数是方法名,调用 del 对象.属性 时自动触发执行方法
  • 第四个参数是字符串,调用 对象.属性.__doc__ ,此参数是该属性的描述信息
class FOO:
    def f1(self):
        return 'f1111'
    def f2(self,value):
        print(value)
    def f3(self):
        print('daya')
    XO = property(fget=f1,fset=f2,fdel=f3,doc='我是说明文档')
obj = FOO()
ret = obj.XO
print(ret)
obj.XO = 1234567
del obj.XO
View Code

成员修饰符:

有两种,公有成员,私有成员

  • 公有成员,在任何地方都能访问
  • 私有成员,只有在类的内部才能方法
class C:
 
    def __init__(self):
        self.name = '公有字段'
        self.__foo = "私有字段
class Foo:
    xo = 'XO'   #公有的静态字段
    __ox = 'ox'     #私有的静态字段 只能内部访问。
    def __init__(self):
        pass
    def fetch(self):
        print(Foo.__ox)
        self.__aaa = 'xxx'
        return self.__aaa     #私有的普通字段,只能内部访问
print(Foo.xo)  #执行公有的静态字段
# print(Foo.__ox)  在外部不能访问
obj = Foo()
obj.fetch()
print(obj.fetch())
公有,私有定义和使用
class Too:
    xxx = '静态字段'
    def func(self):
        print(Too.xxx)
class Foo(Too):
    def shou(self):
        print(Too.xxx)

obj = Too()  #类内部访问
obj.func()
obj1 = Foo()   #派生类访问
obj1.shou()
公有静态字段
class Too:
    __xxx = '静态字段'
    def func(self):
        print(Too.__xxx)
class Foo(Too):
    def shou(self):
        print(Too.__xxx)

obj = Too()  #类内部访问
obj.func()
obj1 = Foo()   #派生不能类访问
obj1.shou()
私有静态字段
  • 公有普通字段:对象可以访问;类内部可以访问;派生类中可以访问
  • 私有普通字段:仅类内部可以访问;

注:如果想要强制访问私有字段,可以通过 【对象._类名__私有字段明 】访问(如:obj._C__foo),不建议强制访问私有成员。

class Too:
    def __init__(self):
        self.name = "公有字段"
    def func(self):
        print(self.name)  # 类内部访问
class Foo(Too):
    def shou(self):
        print(self.name)  #派生类中访问
obj = Too()
obj.name    #通过对象访问
obj.func()  #类内部访问
obj1 = Foo()
obj1.shou()   #派生类中访问
公有普通字段
class Too:
    def __init__(self):
        self.__name = "私有字段"
    def func(self):
        print(self.__name)  # 类内部访问
class Foo(Too):
    def shou(self):
        print(self.__name)  #派生类中不能访问
obj = Too()
# obj.__name    #对象不能访问
obj.func()  #只能类内部可以访问
obj1 = Foo()
obj1.shou()   #派生类不能访问
私有普通字段daunting

注:非要访问私有属性的话,可以通过 对象._类__属性名

面向对象中一些常用特殊方法 :

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

class Foo:
    def __init__(self):
        print('insssssss')
obj = Foo()   自动执行类中__init__方法
执行结果:
insssssss

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

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

class Foo:
    def __call__(self, *args, **kwargs):
        print('caaaaaaaaa')
        return 1111111
obj = Foo()
obj()   #对象后面加括号,触发执行。
ob = Foo()()
print(ob)
执行结果:

caaaaaaaaa
caaaaaaaaa
1111111

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

class Foo:
    def __getitem__(self, item):   #用于索引获取数据
        print(item)
    def __setitem__(self, key, value):  #设置数据
        print(key,value)
    def __delitem__(self, key):          # 删除数据
        print(key)
obj = Foo()
obj['k1'] = 11122223333
del obj['k1']
执行结果:

k1
k1 11122223333
k1

class Foo:
    def __getitem__(self, item):   #用于索引获取数据
        print(item,type(item),'__getitem__')
    def __setitem__(self, key, value):  #设置数据
        print(key,value,'__setitem__')
    def __delitem__(self, key):          # 删除数据
        print(key,'__delitem')
obj = Foo()
obj[1:3]
obj[1:3] = [11,22,33]
del obj[1:3]
执行结果:

slice(1, 3, None) <class 'slice'> __getitem__
slice(1, 3, None) [11, 22, 33] __setitem__
slice(1, 3, None) __delitem

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

class Tpp:
    def __str__(self):
        return '返回之'
ccc = Tpp()
print(ccc)
执行结果:
返回之
class Foo:
    def __init__(self,arg):
        self.xo = arg
    def __str__(self):
        return self.xo
obj = Foo('整差皮了...')
print(obj)

5,__dict__ 获取类 对象的所有的成员

class Tpp:
    def __init__(self,name):
        self.name = name         
    def fff(self):
        print('xxxxxxxxx')
ccc = Tpp('kaishi')
print(ccc.name)         #获取内容
print(ccc.__dict__)    #获取对象的成员
ccc.fff()
执行结果:
kaishi
{'name': 'kaishi'}
xxxxxxxxx
class Tpp:
    country = 'linshi'
    def __init__(self,name,country):
        self.name = name
        self.country = country
    def fff(self):
        print('xxxxxxxxx')
ccc = Tpp('kaishi',1111)
print(ccc.__dict__)
执行结果:
{'country': 1111, 'name': 'kaishi'}

6. __iter__ 

用于迭代器,之所以列表、字典、元组可以进行for循环,是因为类型内部定义了 __iter__ 

class Foo:
    __metaclass__ = 'xxx'
    def __iter__(self):
        yield 1
        yield 2
        yield 3

obj = Foo()
# 如果执行for对象时,自动会执行对象的iter方法,生成器
for i in obj:
    print(i)

异常处理:

异常即是一个事件,该事件会在程序执行过程中发生,影响了程序的正常执行。一般情况下,

在Python无法正常处理程序时就会发生一个异常。

异常是Python对象,表示一个错误。

当Python脚本发生异常时我们需要捕获处理它,否则程序会终止执行。

python中的异常种类非常多,每个异常专门用于处理某一项异常!!!

AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,
导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的
常用异常

比如我们来输出一个int转换,输入数字就可以执行,输入字母出现错误没有捕捉到则会报错

简单的异常处理
li = [2222]                       定义一个列表
inp = input('请输入:')
try:
    xxx = int(inp)
    print(xxx)
    li[1111]                        索引列表的内容         
except IndexError as e:
    print('索引错误')
执行结果:
请输入:
索引错误
IndexError 索引错误
inp = input('请输入:')
try:
    xxx = int(inp)
    print(xxx)
except ValueError as e:
    print('值错误')
ValueError 值错误
dic = {'k1':'213'}
try:
    dic['k20']
except KeyError as e:
    print('取值错误')
执行结果:
取值错误
Keyerror 取值错误

主动触发异常:

try:
    print('12345678')
    raise Exception('差皮了...')
except Exception as e:   #e 封装了错误的信息的对象
    print(e)
执行结果:

12345678
差皮了...

自定义触发异常:

class Foo:
    def __init__(self,arg):
        self.xo = arg
    def __str__(self):
        return self.xo
obj = Foo('整差皮了...')
print(obj)
执行结果:
整差皮了...

调用自定义异常

try:
    raise testError()   //实例化自定义异常类,后面括号可传入参数
except testError,e:
    print e

写程序时需要考虑到try代码块中可能出现的任意异常,可以这样写:

s1 = 'hello'
try:
    int(s1)
except IndexError,e:
    print e
except KeyError,e:
    print e
except ValueError,e:
    print e

万能异常 在python的异常中,有一个万能异常:Exception,他可以捕获任意异常,即:

s1 = 'hello'
try:
    int(s1)
except Exception,e:
    print e

finally

不管try子句是否发生异常都会执行,比如当你在读写文件或者scoket通讯时,不管是否出现异常都应该在结束后关闭文件或者网络套接字,这时就可以把关闭方法放在finally子句中

try:
    f = open('db','a')
f.write(data)
except Exception,e: print e finally: f.close()

忽略所有的异常处理:

 try:
    xxx = 'sss'except:
    pass

这是一种比较危险的用法,它会忽略程序的所有异常而继续的让程序执行下去。
异常处理只需要记住一点:当我们知道某段代码可能会导致某种异常,但我们又不希望程序停止,那么我们就可以根据需要添加异常处理。

 单例模式

单例,顾名思义单个实例

实例:

面向对象场景一:

单例模式  只有一个实例
所有的实例中封装的内容都相同时,用单例模式
  连接池
class ConnectionPool:
    __instance = None

    def __init__(self):
        self.ip = '1.2.1.1'
        self.port = 3300
        self.username = 'kaisshi'
        self.pwd = '123123'
        self.liebiao = [1,2,3,4,5,6,7,8,9,10]
    @staticmethod
    def get_instance():   #判断如果类中静态字段有值就执行,
        if ConnectionPool.__instance:
            return ConnectionPool.__instance
                     #否则就执行类对象
        else:  # 创建一个对象,并将对象赋值给静态字段
            ConnectionPool.__instance = ConnectionPool()
            return ConnectionPool.__instance
obj = ConnectionPool.get_instance()   #执行私有方法
print(obj)
obj1 = ConnectionPool.get_instance()
print(obj)
View Code

面向对象场景二:

如:创建对数据库操作的公共类

# #### 定义类 ####

class DbHelper(object):

    def __init__(self):
        self.hostname = '1.1.1.1'
        self.port = 3306
        self.password = 'pwd'
        self.username = 'root'

    def fetch(self):
        # 连接数据库
        # 拼接sql语句
        # 操作
        pass

    def create(self):
        # 连接数据库
        # 拼接sql语句
        # 操作
        pass

    def remove(self):
        # 连接数据库
        # 拼接sql语句
        # 操作
        pass

    def modify(self):
        # 连接数据库
        # 拼接sql语句
        # 操作
        pass

# #### 操作类 ####

db = DbHelper()
db.create()
View Code

场景2实现 web应用:

from wsgiref.simple_server import make_server
def RunServer(environ, start_response):
    start_response(status='200 OK', headers=[('Content-Type', 'text/html')])
    url = environ['PATH_INFO']

    # return "OldBoy jiaogewwwwwwwwwwssssssssssss"
if __name__ == '__main__':
    httpd = make_server('', 8000, RunServer)
    print("Serving HTTP on port 8000...")
    httpd.serve_forever()
#
#



from wsgiref.simple_server import make_server

class ConnectionPool:

    __instance = None

    def __init__(self):
        self.ip = "1.1.1.1"
        self.port = 3306
        self.pwd = "123123"
        self.username = 'xxxx'
        # 去连接
        self.conn_list = [1,2,3,4,5,6,7,8,9,10]

    @staticmethod
    def get_instance():
        if ConnectionPool.__instance:
            return ConnectionPool.__instance
        else:
            # 创建一个对象,并将对象赋值给静态字段 __instance
            ConnectionPool.__instance = ConnectionPool()
            return ConnectionPool.__instance

    def get_connection(self):
        # 获取连接
        import random
        r = random.randrange(1,11)
        return r

def index():
    # p = ConnectionPool()
    # print(p)
    p = ConnectionPool.get_instance()
    conn = p.get_connection()
    return "iiiiiii" + str(conn)

def news():
    return 'nnnnnnn'

def RunServer(environ, start_response):
    start_response(status='200 OK', headers=[('Content-Type', 'text/html')])

    url = environ['PATH_INFO']
    if url.endswith('index'):
        ret = index()
        return ret
    elif url.endswith('news'):
        ret = news()
        return ret
    else:
        return "404"

if __name__ == '__main__':
    httpd = make_server('', 8008, RunServer)
    print("Serving HTTP on port 8008...")
    httpd.serve_forever()
View Code
原文地址:https://www.cnblogs.com/guokaixin/p/5554523.html