重新学习python系列(二)? WTF?

判断class的类型,可以使用isinstance()函数。

isinstance()判断的是一个对象是否是该类型本身,或者位于该类型的父继承链上。

>>> a = Animal() >>> d = Dog() >>> h = Husky()>>> isinstance(h, Husky)
True>>> isinstance(h, Dog)
True

能用type()判断的基本类型也可以用isinstance()判断:
并且还可以判断一个变量是否是某些类型中的一种,比如下面的代码就可以判断是否是str或者unicode:

>>> isinstance(‘a‘, (str, unicode))
True
>>> isinstance(u‘a‘, (str, unicode))
True

dir()

获得一个对象的所有属性和方法
返回一个包含字符串的list

如果也想用len(myObj)的话,就自己写一个__len__()方法:

>>> class MyObject(object):
...     def __len__(self):
...         return 100
...
>>> obj = MyObject()
>>> len(obj)
100

获取对象信息:

配合getattr()setattr()以及hasattr(),我们可以直接操作一个对象的状态:

>>> class MyObject(object):
...     def __init__(self):
...         self.x = 9
...     def power(self):
...         return self.x * self.x
...
>>> obj = MyObject()
>>> hasattr(obj, ‘x‘) # 有属性‘x‘吗?
True
>>> obj.x
9
>>> hasattr(obj, ‘y‘) # 有属性‘y‘吗?
False
>>> setattr(obj, ‘y‘, 19) # 设置一个属性‘y‘
>>> hasattr(obj, ‘y‘) # 有属性‘y‘吗?
True
>>> getattr(obj, ‘y‘) # 获取属性‘y‘
19
>>> obj.y # 获取属性‘y‘
19

可以传入一个default参数,如果属性不存在,就返回默认值:

>>> getattr(obj, ‘z‘, 404) # 获取属性‘z‘,如果不存在,返回默认值404
404

也可以获得对象的方法:

>>> hasattr(obj, ‘power‘) # 有属性‘power‘吗?
True
>>> getattr(obj, ‘power‘) # 获取属性‘power‘
<bound method MyObject.power of <__main__.MyObject object at 0x108ca35d0>>
>>> fn = getattr(obj, ‘power‘) # 获取属性‘power‘并赋值到变量fn
>>> fn # fn指向obj.power
<bound method MyObject.power of <__main__.MyObject object at 0x108ca35d0>>
>>> fn() # 调用fn()与调用obj.power()是一样的
81

绑定:
http://www.cnblogs.com/yhl664123701/p/6051448.html

# -*-coding:utf-8-*-
from types import MethodType

def set_age(self, arg):
    self.age = arg

class Student(object):
    pass

s = Student()
#给student 创建一个方法 但这里不是在class中创建而是创建了一个链接把外部的set_age 方法用链接知道Student内
s.set_age = MethodType(set_age,s,Student)
s.set_age(213)   #调用实例方法
print s.age
# -*-coding:utf-8-*-
from types import MethodType

def set_age(self, arg):
    self.age = arg

class Student(object):
    pass

#直接用类来创建一个方法  不过此时还是用链接的方式在类外的内存中创建
Student.set_age = MethodType(set_age,Student)
#此时在创建实例的时候外部方法 set_age 也会复制 这些实例和Student类都指向同一个set_age方法
new1 = Student()
new1.set_age(132)
print new1.age

__slots__变量,来限制该class能添加的属性:
使用__slots__要注意,__slots__定义的属性仅对当前类起作用,对继承的子类是不起作用的:

除非在子类中也定义__slots__,这样,子类允许定义的属性就是自身的__slots__加上父类的__slots__

>>> class Student(object):
...     __slots__ = (‘name‘, ‘age‘) # 用tuple定义允许绑定的属性名称
...

Mixin继承

为了更好地看出继承关系,我们把RunnableFlyable改为  RunnableMixin  和  FlyableMixin

定制类

__str__(),而是__repr__(),两者的区别是__str__()返回用户看到的字符串

class Student(object):
    def __init__(self, name):
        self.name = name
    def __str__(self):
        return ‘Student object (name=%s)‘ % self.name
    __repr__ = __str__

__iter__

如果一个类想被用于for ... in循环,类似list或tuple那样,

就必须实现一个__iter__()方法,该方法返回一个迭代对象,

然后,Python的for循环就会不断调用该迭代对象的next()方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。

class Fib(object):
    def __init__(self):
        self.a, self.b = 0, 1 # 初始化两个计数器a,b

    def __iter__(self):
        return self # 实例本身就是迭代对象,故返回自己

    def next(self):
        self.a, self.b = self.b, self.a + self.b # 计算下一个值
        if self.a > 100000: # 退出循环的条件
            raise StopIteration();
        return self.a # 返回下一个值

__getitem__

Fib实例虽然能作用于for循环,看起来和list有点像,但是,把它当成list来使用还是不行,比如,取第5个元素:

class Fib(object):
    def __getitem__(self, n):
        a, b = 1, 1
        for x in range(n):
            a, b = b, a + b
        return a

__getattr__
正常情况下,当我们调用类的方法或属性时,如果不存在,就会报错。

class Student(object):

    def __init__(self):
        self.name = ‘Michael‘

    def __getattr__(self, attr):
        if attr==‘score‘:
            return 99

>> s.score99

__call__
还可以定义参数。对实例进行直接调用就好比对一个函数进行调用一样,所以你完全可以把对象看成函数,把函数看成对象,因为这两者之间本来就没啥根本的区别。

通过callable()函数,我们就可以判断一个对象是否是“可调用”对象。

class Student(object):
    def __init__(self, name):
        self.name = name

    def __call__(self):
        print(‘My name is %s.‘ % self.name)

>>> s = Student(‘Michael‘)
>>> s()
My name is Michael.

动态创建类

>>> def fn(self, name=‘world‘): # 先定义函数
...     print(‘Hello, %s.‘ % name)
...
>>> Hello = type(‘Hello‘, (object,), dict(hello=fn)) # 创建Hello class
>>> h = Hello()
>>> h.hello()
Hello, world.
>>> print(type(Hello))
<type ‘type‘>
>>> print(type(h))
<class ‘__main__.Hello‘>

错误处理
当我们认为某些代码可能会出错时,就可以用try来运行这段代码,

如果执行出错,则后续代码不会继续执行,

而是直接跳转至错误处理代码,即except语句块,

执行完except后,如果有finally语句块,则执行finally语句块(是否有错误都会执行),至此,执行完毕

try:
    print ‘try...‘
    r = 10 / 0
    print ‘result:‘, r
except ZeroDivisionError, e:
    print ‘except:‘, e
finally:
    print ‘finally...‘
print ‘END‘

Python的错误其实也是class,所有的错误类型都继承自BaseException,所以在使用except时需要注意的是,它不但捕获该类型的错误,还把其子类也“一网打尽”

try:
    foo()
except StandardError, e:
    print ‘StandardError‘
except ValueError, e:
    print ‘ValueError‘

第二个except永远也捕获不到ValueError,因为ValueErrorStandardError的子类,如果有,也被第一个except给捕获了。

常见的错误类型和继承关系:https://docs.python.org/2/library/exceptions.html#exception-hierarchy

记录错误

如果不捕获错误,自然可以让Python解释器来打印出错误堆栈,但程序也被结束了。既然我们能捕获错误,就可以把错误堆栈打印出来,然后分析错误原因,同时,让程序继续执行下去。

Python内置的logging模块可以非常容易地记录错误信息:

import logging

def foo(s):
    return 10 / int(s)

def bar(s):
    return foo(s) * 2

def main():
    try:
        bar(‘0‘)
    except StandardError, e:
        logging.exception(e)

main()
print ‘END‘

通过配置,logging还可以把错误记录到日志文件里,方便事后排查。

抛出错误: raise

class FooError(StandardError):
    pass

def foo(s):
    n = int(s)
    if n==0:
        raise FooError(‘invalid value: %s‘ % s)
    return 10 / n
时间: 2024-12-20 19:30:47

重新学习python系列(二)? WTF?的相关文章

重新学习python系列(一)? WTF?

重新学习python:两年前学了点python之后就一直没做做过啥项目, 基本上全忘光了,复习一下搞点事情 or |and & ord() ascii转16进制 chr()  16进制转ascii >>> u'ABC'.encode('utf-8') 'ABC' >>> u'中文'.encode('utf-8') '\xe4\xb8\xad\xe6\x96\x87' >>> 'abc'.decode('utf-8') u'abc' >&g

Telegram学习解析系列(二):这我怎么给后台传输数据?

写在前面: 在iOS开发的过程中,有很多时候我们都在和数据打交道,最基本的就是数据的下载和上传了,估计很多很多的小伙伴都在用AFNetworking与后台数据打交道,可有没有想过,哪天AFNetworking你不能用了或者不会用了怎么办?可能你心中疑惑了,这三方只要更新,存在怎么会不能用或者我怎么会不会用了,在没有看Telegram源码之前,我也是这么想的,看了Telegram源码就不会再这么想了,以后我会把自己看的Telegram源码部分的总结和经验一点点的整理分享出来,整理成这个Telegr

重新学习python系列(三)? WTF?

读取文件: try: f = open('/path/to/file', 'r') print(f.read()) finally: if f: f.close() ------------------------------------- with open('/path/to/file', 'r') as f: print(f.read()) ------------------------------------- 调用readline()可以每次读取一行内容,调用readlines()一

重新学习python系列(四)? WTF?

多进程: fork()调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程), 然后,分别在父进程和子进程内返回getppid()得到父进程的IDgetpid() 得到当前进程的ID # multiprocessing.py import os print 'Process (%s) start...' % os.getpid() pid = os.fork() if pid==0: print 'I am child process (%s) and my par

【Python】Java程序员学习Python(二)— 开发环境搭建

巧妇难为无米之炊,我最爱的还是鸡蛋羹,因为我和鸡蛋羹有段不能说的秘密. 不管学啥,都要有环境,对于程序员来说搭建个开发环境应该不是什么难题.按顺序一步步来就可以,我也只是记录我的安装过程,你也可以滴. 一.准备Java环境 我已经说过了,其实我是一个Java程序员,所以学习过程中会有很多Java相关的内容和对比.先介绍下我的基本情况 jdk1.8 eclipse即可,版本最新的 怎么安装java,配置环境变量什么的,我都不会再说了,我这不是小白教程,我相信具备一定的能力. 二.准备Python环

Python 系列 二 数据类型

1.1 Python中的数据类型 Python使用对象模型来储存数据,每一个数据类型都有一个内置的类,每新建一个数据,实际就是在初始化生成一个对象,既所有数据都是对象: 对象三个特种: 1.身份:内存地址,可以用id()获取 2.类型:决定了该对象可以保存什么类型值,可以操作何种操作,需要遵循什么规则,可以用type()获取 3.值:对象保存的真实数据 1.2 数字 1.2.1 int (整型) 1.在32位机器上,整数的位数为32位,取值范围为-2**31-2**31-1,即-21474836

2017寒假零基础学习Python系列之函数之 函数之定义可变参数

若想让函数接受任意个参数,就可以定义一个可变的参数: def fn(*args): print args fn() >>>() fn(1,2,5,6) >>>(1,2,5,6) 原理是Python解释器把传入的一组参数封装在一个tuple传递给可变参数,因此在函数内部,直接把变量args看成一个tuple就好了,目的是简化调用 小习题:假设我们要计算任意个数的平均值,就可以定义一个可变参数: def average(*args): ... 这样,在调用的时候,可以这样写

2017寒假零基础学习Python系列之函数之 返回多个值

Python也和C语言一样有自己的标准库,不过在Python中叫做模块(module),这个和C语言中的头文件以及Java中的包类似,其中math就是其中之一,math模块中提供了sin()和cos()函数 引用Python中模块(以引用math为例)的格式为:import math 以一个计算游戏中坐标的例子来说吧: import math def move(x,y,step,angle): nx = x + step * math.cos(angle) ny = y - step * mat

学习CNN系列二:训练过程

卷积神经网络在本质上是一种输入到输出的映射,它能够学习大量的输入与输出之间的映射关系,而不需要任何输入和输出之间精确的数学表达式,只要用已知的模式对卷积神经网络加以训练,网络就具有输入.输出之间映射的能力. 其训练算法与传统的BP算法类似,主要分4步,可分为2个阶段: 第一阶段,前向传播阶段: (1)从样本集中取一个样本,将样本输入网络: (2)计算相应的实际输出. 在此阶段,信息从输入层经过逐级的变换,传送到输出层.这个过程也是网络在完成训练后正常运行时执行的过程. 第二阶段,后向传播阶段: