对象类型
一、isinstance(obj, cls)
检查是否obj是否是类 cls 的对象
1 class Foo(object): 2 pass 3 4 obj = Foo() 5 6 isinstance(obj, Foo)
二、issubclass(sub, super)
检查sub类是否是 super 类的派生类
1 class Foo(object): 2 pass 3 4 class Bar(Foo): 5 pass 6 7 issubclass(Bar, Foo)
可变类型vs不可变类型和深拷贝vs浅拷贝
可变类型 Vs 不可变类型
可变类型(mutable):列表,字典
不可变类型(unmutable):数字,字符串,元组
这里的可变不可变,是指内存中的那块内容(value)是否可以被改变
# -*- coding: utf-8 -*-
'''
# @Datetime: 2019/02/13
# @author: Zhang Yafei
'''
a = (1,2,3,'hello')
b = a
print(id(a))
print(id(b))
# 263034329432
# 263034329432
a = (23,46)
print(a)
print(b)
print(id(a))
print(id(b))
# (23, 46)
# (1, 2, 3, 'hello')
# 990975432776
# 990975252824
a = 'l love you'
b = a
print(b)
print(id(a))
print(id(b))
# l love you
# 1082135746864
# 1082135746864
a = 'you lie'
print(a)
print(b)
print(id(a))
print(id(b))
# you lie
# l love you
# 1082138333848
# 1082135746864
a = 111
b = a
print(a)
print(b)
print(id(a))
print(id(b))
# 111
# 1880059248
# 1880062416
a = 12
print(a)
print(b)
print(id(a))
print(id(b))
# 12
# 111
# 1880062416
# 1880062416
a = [1,2,3]
b = a
print(b)
print(id(a))
print(id(b))
# [1, 2, 3]
# 880126268808
# 880126268808
a[1] = 22
print(a)
print(b)
print(id(a))
print(id(b))
# [1, 22, 3]
# [1, 22, 3]
# 880126268808
# 880126268808
a = {'name':'zhang','sex':0}
b = a
print(b)
print(id(a))
print(id(b))
# {'name': 'zhang', 'sex': 0}
# 75290721448
# 75290721448
a['age'] = 23
print(a)
print(b)
print(id(a))
print(id(b))
# {'name': 'zhang', 'sex': 0, 'age': 23}
# {'name': 'zhang', 'sex': 0, 'age': 23}
# 75290721448
# 75290721448# [1, 2, 3]
"""
例如数值、字符串,元组(tuple不允许被更改)采用的是复制的方式(深拷贝?),也就是说当将另一个变量B赋值给变量A时,
虽然A和B的内存空间仍然相同,但当A的值发生变化时,会重新给A分配空间,A和B的地址变得不再相同
而对于像字典(dict),列表(List)等,改变一个就会引起另一个的改变,也称之为浅拷贝
"""
深拷贝 Vs 浅拷贝
copy.copy() 浅拷贝
copy.deepcopy() 深拷贝
浅拷贝是新创建了一个跟原对象一样的类型,但是其内容是对原对象元素的引用。这个拷贝的对象本身是新的,但内容不是。拷贝序列类型对象(列表\元组)时,默认是浅拷贝。
深拷贝,在内存中将所有的数据重新创建一份(排除最后一层,即:python内部对字符串和数字的优化)
import copy
n1 = "'zhang'/23"
n2 = n1
n3 = copy.copy(n1)
n4 = copy.deepcopy(n1)
print(n1, n2, n3, n4)
# 'zhang'/23 'zhang'/23 'zhang'/23 'zhang'/23
n1 = 'kobe'
print(n1, n2, n3, n4)
# kobe 'zhang'/23 'zhang'/23 'zhang'/23
n1 = {"k1": "zhang", "k2": 23, "k3": ["kobe", 42]}
n2 = n1
n3 = copy.copy(n1)
n4 = copy.deepcopy(n1)
print(n1, n2, n3, n4)
# {'k1': 'zhang', 'k2': 23, 'k3': ['kobe', 42]} {'k1': 'zhang', 'k2': 23, 'k3': ['kobe', 42]} {'k1': 'zhang', 'k2': 23, 'k3': ['kobe', 42]} {'k1': 'zhang', 'k2': 23, 'k3': ['kobe', 42]}
n1['k3'].append(0)
print(n1, n2, n3, n4)
# {'k1': 'zhang', 'k2': 23, 'k3': ['kobe', 42, 0]} {'k1': 'zhang', 'k2': 23, 'k3': ['kobe', 42, 0]} {'k1': 'zhang', 'k2': 23, 'k3':
# ['kobe', 42, 0]} {'k1': 'zhang', 'k2': 23, 'k3': ['kobe', 42]}
总结
1:对于不可变对象(如数字/字符串/元组),无论是深拷贝还是浅拷贝,内存地址和值都是相同的,没有意义;
2:对于可变的对象,如列表,字典类型的:
浅拷贝:值和地址都是相同的
深拷贝:值相同,地址不同
例如数值、字符串,元组(tuple不允许被更改)采用的是复制的方式(深拷贝?),也就是说当将另一个变量B赋值给变量A时,
虽然A和B的内存空间仍然相同,但当A的值发生变化时,会重新给A分配空间,A和B的地址变得不再相同
而对于像字典(dict),列表(List)等,改变一个就会引起另一个的改变,也称之为浅拷贝
异常处理
异常,在程序运行时出现非正常情况时会被抛出,比如常见的名称错误、键错误等。当程序发生一些错误的时候,该如何处理。即异常预处理方案。
例如:空列表弹出报错
In [26]: a = [] In [27]: a.pop() --------------------------------------------------------------------------- IndexError Traceback (most recent call last) <ipython-input-27-9c070c907602> in <module>() ----> 1 a.pop() IndexError: pop from empty list
1、捕获异常
try: pass except Exception,ex: pass
In [28]: try: ...: a.pop() ...: except IndexError as e: ...: print(e) ...: pop from empty list
二、异常种类
AttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x IOError 输入/输出异常;基本上是无法打开文件 ImportError 无法引入模块或包;基本上是路径问题或名称错误 IndentationError 语法错误(的子类) ;代码没有正确对齐 IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5] KeyError 试图访问字典里不存在的键 KeyboardInterrupt Ctrl+C被按下 NameError 使用一个还未被赋予对象的变量 SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了) TypeError 传入对象类型与要求的不符合 UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量, 导致你以为正在访问它 ValueError 传入一个调用者不期望的值,即使值的类型是正确的 常用异常