python之路 面向对象进阶篇
一、字段
字段包括:普通字段和静态字段,他们在定义和使用中有所区别,而最本质的区别是内存中保存的位置不同,
- 普通字段属于对象
 - 静态字段属于类
 
class Province:
    # 静态字段
    country = '中国'
    def __init__(self, name):
        # 普通字段
        self.name = name
# 直接访问普通字段
obj = Province('河北省')
print obj.name
# 直接访问静态字段
Province.country
由上述代码可以看出【普通字段需要通过对象来访问】【静态字段通过类访问】,在使用上可以看出普通字段和静态字段的归属是不同的。
- 静态字段在内存中只保存一份
 - 普通字段在每个对象中都要保存一份
 
应用场景: 通过类创建对象时,如果每个对象都具有相同的字段,那么就使用静态字段
二、方法
方法包括:普通方法、静态方法和类方法,三种方法在内存中都归属于类,区别在于调用方式不同。
- 普通方法:由对象调用;至少一个self参数;执行普通方法时,自动将调用该方法的对象赋值给self;
 - 类方法:由类调用; 至少一个cls参数;执行类方法时,自动将调用该方法的类复制给cls;
 - 静态方法:由类调用;无默认参数;
 
#方法的定义和使用
class Foo:
    def __init__(self, name):
        self.name = name
    def ord_func(self):
        """ 定义普通方法,至少有一个self参数 """
        # print self.name
        print '普通方法'
    @classmethod
    def class_func(cls):
        """ 定义类方法,至少有一个cls参数 """
        print '类方法'
    @staticmethod
    def static_func():
        """ 定义静态方法 ,无默认参数"""
        print '静态方法'
# 调用普通方法
f = Foo()
f.ord_func()
# 调用类方法
Foo.class_func()
# 调用静态方法
Foo.static_func()
三、属性
如果你已经了解Python类中的方法,那么属性就非常简单了,因为Python中的属性其实是普通方法的变种。
对于属性,有以下三个知识点:
- 属性的基本使用
 - 属性的两种定义方式
 
1、创建调用属性
# ############### 定义 ###############
class Foo: def func(self):
pass # 定义属性
@property
def prop(self):
pass
# ############### 调用 ###############
foo_obj = Foo() foo_obj.func()
foo_obj.prop #调用属性
由属性的定义和调用要注意一下几点:
- 定义时,在普通方法的基础上添加 @property 装饰器;
 - 定义时,属性仅有一个self参数
 - 调用时,无需括号
方法:foo_obj.func()
属性:foo_obj.prop 
注意:属性存在意义是:访问属性时可以制造出和访问字段完全相同的假象
属性由方法变种而来,如果Python中没有属性,方法完全可以代替其功能。
实例:对于主机列表页面,每次请求不可能把数据库中的所有内容都显示到页面上,而是通过分页的功能局部显示,所以在向数据库中请求数据时就要显示的指定获取从第m条到第n条的所有数据(即:limit m,n),这个分页的功能包括:
- 根据用户请求的当前页和总数据条数计算出 m 和 n
 - 根据m 和 n 去数据库中请求数据
 
class Pager:
    def __init__(self, current_page):
        # 用户当前请求的页码(第一页、第二页...)
        self.current_page = current_page
        # 每页默认显示10条数据
        self.per_items = 10
    @property
    def start(self):
        val = (self.current_page - 1) * self.per_items
        print(val)
        return val
    @property
    def end(self):
        val = self.current_page * self.per_items
        print(val)
        return val
# ############### 调用 ###############
p = Pager(3)
p.start
# p.end
# p.start 就是起始值,即:m
# p.end   就是结束值,即:n
从上述可见,Python的属性的功能是:属性内部进行一系列的逻辑计算,最终将计算结果返回。
2、两种定义属性的方法
属性的定义有两种方式:
- 装饰器 即:在方法上应用装饰器
 - 静态字段 即:在类中定义值为property对象的静态字
 
装饰器方法
# ############### 定义 ###############
class Goods(object): @property
def price(self):
print '@property' @price.setter
def price(self, value):
print '@price.setter' @price.deleter
def price(self):
print '@price.deleter' # ############### 调用 ###############
obj = Goods() obj.price # 自动执行 @property 修饰的 price 方法,并获取方法的返回值 obj.price = 123 # 自动执行 @price.setter 修饰的 price 方法,并将 123 赋值给方法的参数 del obj.price # 自动执行 @price.deleter 修饰的 price 方法
由于新式类中具有三种访问方式,我们可以根据他们几个属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除
实例
class Goods(object):
    def __init__(self):
        # 原价
        self.original_price = 100
        # 折扣
        self.discount = 0.8
    @property
    def price(self):
        # 实际价格 = 原价 * 折扣
        new_price = self.original_price * self.discount
        return new_price
    @price.setter
    def price(self, value):
        self.original_price = value
    @price.deltter
    def price(self, value):
        del self.original_price
obj = Goods()
obj.price         # 获取商品价格
obj.price = 200   # 修改商品原价
del obj.price     # 删除商品原价
静态字段方法
property的构造方法中有个四个参数
- 第一个参数是方法名,调用 
对象.属性时自动触发执行方法 - 第二个参数是方法名,调用 
对象.属性 = XXX时自动触发执行方法 - 第三个参数是方法名,调用 
del 对象.属性时自动触发执行方法 - 第四个参数是字符串,调用 
对象.属性.__doc__,此参数是该属性的描述信息 
公有成员,在任何地方都能访问
私有成员,只有在类的内部才能方法
私有成员和公有成员的定义不同:私有成员命名时,前两个字符是下划线
例如:
class C(object):
def __init__(self):
self.name = '公有字段'
self.__foo = "私有字段"
静态字段
公有静态字段:类可以访问,类内部可以访问,派生类中可以访问;私有静态字段:仅类内部可以访问;
公有类:
#!/usr/bin/env python3
#coding:utf8 class Person(object):
name = "公有字段属性"
def __init__(self):
pass
def one(self):
print(self.name)
class Child(Person):
def two(self):
print(self.name)
#类访问
print(Person.name)
obj = Person()
#类的内部访问
obj.one() ch = Child()
#子类可以访问
ch.two()
私有字段
class Person(object):
__name = '私有字段'
def __init__(self):
pass
def one(self):
print(self.__name)
class Child(Person):
def two(self):
print(Person.__name)
#类访问
print(Person.__name)
报错:
print(Person.__name)
ttributeError: type object 'Person' has no attribute '__name' #类的内部访问
obj = Person()
obj.one()
结果:
私有字段
#子类访问
obj = Child()
obj.two()
报错:
print(Person.__name)
AttributeError: type object 'Person' has no attribute '_Child__name'
公有普通字段:对象可以访问;类内部可以访问;派生类中可以访问
私有普通字段:仅类内部可以访问;
**ps:如果想要强制访问私有字段,可以通过 【对象._类名__私有字段明 】访问(如:obj._C__foo),不建议强制访问私有成员。**
公有字段访问:
class Person(object):
def __init__(self):
self.name = '刘耀'
def one(self):
print(self.name)
class Child(Person):
def two(self):
print(self.name)
obj = Person()
#通过类访问
print(obj.name)
#通过内部访问
obj.one()
#子类访问
objj = Child()
objj.two()
私有类访问:
class Person(object):
def __init__(self):
self.__name = '刘耀'
def one(self):
print(self.__name)
class Child(Person):
def two(self):
print(self.__name)
obj = Person()
#通过类访问
print(obj.__name)
#通过内部访问
obj.one()
#子类访问
objj = Child()
objj.two()
方法、属性的访问于上述方式相似,即:私有成员只能在类内部使用
四、异常
1、异常基础
案例:
num1 = input('num1:')
num2 = input('num2:')
try:
    num1 = int(num1)
    num2 = int(num2)
    result = num1 + num2
except Exception as e:
    print(e)
#当我输入的都是数字的时候,不异常
#当我输入有一个是非数字的时候 打印异常
结果:
num1:1
num2:m
invalid literal for int() with base 10: 'm'
2、异常种类
1)常用异常 AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x
IOError 输入/输出异常;基本上是无法打开文件
ImportError 无法引入模块或包;基本上是路径问题或名称错误
IndentationError 语法错误(的子类) ;代码没有正确对齐
IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5]
KeyError 试图访问字典里不存在的键
KeyboardInterrupt Ctrl+C被按下
NameError 使用一个还未被赋予对象的变量
SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了)
TypeError 传入对象类型与要求的不符合
UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量,导致你以为正在访问它
ValueError 传入一个调用者不期望的值,即使值的类型是正确的 2)更多异常 ArithmeticError
AssertionError
AttributeError
BaseException
BufferError
BytesWarning
DeprecationWarning
EnvironmentError
EOFError
Exception
FloatingPointError
FutureWarning
GeneratorExit
ImportError
ImportWarning
IndentationError
IndexError
IOError
KeyboardInterrupt
KeyError
LookupError
MemoryError
NameError
NotImplementedError
OSError
OverflowError
PendingDeprecationWarning
ReferenceError
RuntimeError
RuntimeWarning
StandardError
StopIteration
SyntaxError
SyntaxWarning
SystemError
SystemExit
TabError
TypeError
UnboundLocalError
UnicodeDecodeError
UnicodeEncodeError
UnicodeError
UnicodeTranslateError
UnicodeWarning
UserWarning
ValueError
Warning
ZeroDivisionError
案例:
IndexError
dic = ["liuyao", '18']
try:
dic[2]
except IndexError as e:
print (e)
#因为没有索引是2的打印异常
list index out of range
KeyError
dic = {'k1':'v1',}
try:
    dic['k2']
except KeyError as e:
    print(e)
万能异常 在python的异常中,有一个万能异常:Exception,他可以捕获任意异常,即:
s1 = 'hello'
try:
int(s1)
except Exception as e:
print(e)
结果:
invalid literal for int() with base 10: 'hello'
3、主动出发异常
try:
raise Exception('错误了。。。')
except Exception as e:
print (e)
结果:
错误了
4、自定义异常
class Liuyaoerror(Exception):
def __init__(self, msg):
self.message = msg def __str__(self):
return self.message
try:
raise Liuyaoerror('我的异常')
except Liuyaoerror as e:
print (e)
5、断言
# assert 条件 assert 1 == 1 assert 1 == 2
五、反射
python中的反射功能是由以下四个内置函数提供:hasattr、getattr、setattr、delattr,改四个函数分别用于对对象内部执行:检查是否含有某成员、获取成员、设置成员、删除成员。
class Foo(object):
    def __init__(self):
        self.name = 'liuyao'
    def func(self):
        return 'func'
    def niubi(self):
        return 'niubi'
obj = Foo()
#### 检查是否含有成员 ####
a=hasattr(obj, 'name')
b=hasattr(obj, 'func')
print(a,b)
结果:
True True
如果不存在那么
False
#### 获取成员 ####
print(getattr(obj, 'name'))
print(getattr(obj, 'func'))
结果:
liuyao
<bound method Foo.func of <__main__.Foo object at 0x004DB350>>
如果要获取到并且执行方法:
print(getattr(obj, 'func')())
结果:
我的func
##### 设置成员 ####
setattr(obj, 'age', 18)
setattr(obj, 'show', lambda num: num + 1)
print(getattr(obj, 'age'))
print(getattr(obj, 'show'))
结果:
18
<function <lambda> at 0x004856A8>
# # #### 删除成员 ####
delattr(obj,'name')
# delattr(obj,'func')
print(getattr(obj, 'name'))
结果:
因为self.name在内存中已经被删除
所以:
print(getattr(obj, 'name'))
AttributeError: 'Foo' object has no attribute 'name'
python之路 面向对象进阶篇的更多相关文章
- python之路----面向对象进阶一
		
一.isinstance和issubclass isinstance(obj,cls)检查是否obj是否是类 cls 的对象 class Foo(object): pass obj = Foo() i ...
 - python之路——面向对象进阶
		
阅读目录 isinstance和issubclass 反射 setattr delattr getattr hasattr __str__和__repr__ __del__ item系列 __geti ...
 - python之路:进阶篇 内置函数
		
li = [11, 22, 33] news = map( li = [100, 2200, 3300] news = map( [13, 24, 35] [11, 11, 11] [22, 4 ...
 - python之路:进阶篇
		
> ) { ; } printf(;} print i >>> >>> == : name == == ...
 - python之路----面向对象进阶二
		
item系列 __getitem__\__setitem__\__delitem__ class Foo: def __init__(self,name,age,sex): self.name = n ...
 - Python开发【第七篇】:面向对象 和 python面向对象进阶篇(下)
		
Python开发[第七篇]:面向对象 详见:<Python之路[第五篇]:面向对象及相关> python 面向对象(进阶篇) 上一篇<Python 面向对象(初级篇)> ...
 - Python之路【第九篇】:Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy
		
Python之路[第九篇]:Python操作 RabbitMQ.Redis.Memcache.SQLAlchemy Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用 ...
 - python之路——面向对象(进阶篇)
		
面向对象进阶:类成员.类成员的修饰符.类的特殊成员 类成员 类成员分为三大类:字段.方法.属性 一.字段 静态字段 (属于类) 普通字段(属于对象) class City: # 静态字段 countr ...
 - Python之路【第九篇】:Python面向对象
		
阅读目录 一.三大编程范式 编程范式即编程的方法论,标识一种编程风格: 大家学习了基本的python语法后,大家可以写python代码了,然后每个人写代码的风格不同,这些不同的风格就代表了不同的流派: ...
 
随机推荐
- Storm系统架构以及代码结构学习
			
转自:http://blog.csdn.net/androidlushangderen/article/details/45955833 storm学习系列:http://blog.csdn.net/ ...
 - jquery 改变checkbox的值
			
似乎没什么用... <script> $(document).ready(function(){ $("#comment").change(function(){ va ...
 - iOS-数组,字典常用的字面量写法
			
解决方法: //用字面量创建数组 NSArray *array = @[@"one",@"two"]; //用字面量创建字典 NSDictionary *dic ...
 - python之进制转换
			
Python中二进制是以0b开头的: 例如: 0b11 则表示十进制的3 8进制是以0开头的: 例如: 011则表示十进制的9 16进制是以0x开头的: 例如: 0x11则表示十进制 ...
 - 《转》适用于开发人员的10个最佳ASP.NET的CMS系统
			
1) mojoportal mojoPortal 是一个开源的.用 C# 编写的站点框架和内容管理系统,可以运行在 Windows 中的 ASP.NET 和 Linux/Mac OS X 中的 Mon ...
 - null!= xxx 和  xxx!=null有什么区别?
			
从意义上将没有区别,从编程规范上讲,第一种写法是为了防止写成:null = xxx
 - mac同时安装多个jdk
			
DK8 GA之后,小伙伴们喜大普奔,纷纷跃跃欲试,想体验一下Java8的Lambda等新特性,可是目前Java企业级应用的主打版本还是JDK6, JDK7.因此,我需要在我的电脑上同时有JDK8,JD ...
 - 网络模型+三次握手+四次挥手+DNS+HTTPS
			
网络模型+三次握手+四次挥手+DNS+HTTPS 这篇文章十分精华,所以整理一下: 一.网络模型 OSI七层模型,和TCP/IP五层模型(更为普遍) TCP/IP 协议集: 二.TCP协议(传输层)建 ...
 - 关于redux应用
			
redux 有点类似flux.但是我觉得远比flux要复杂.因为他非常的绕.一般搭配使用是redux 和react-redux 使用. 主要的思路就是: 写action:动作类型 写reducer:动 ...
 - Ubuntu 14.04下安装GitLab
			
0.硬件要求 官方要求:http://doc.gitlab.com/ce/install/requirements.html CPU 1 core works supports up to 100 u ...