您的位置:首页 > 编程语言 > Python开发

python3 基础学习笔记

2018-03-23 10:19 288 查看

记录学习廖雪峰的python教程,摘要重点

1、基础

1.1数据类型和变量

l  字符串:
转义字符
\
可以转义很多字符,比如
\n
表示换行,
\t
表示制表符,字符
\
本身也要转义,所以
\\
表示的字符就是
\

为了简化,Python还允许用
r''
表示
''
内部的字符串默认不转义
如果字符串内部有很多换行,用
\n
写在一行里不好阅读,为了简化,Python允许用
'''...'''
的格式表示多行内容
 
l  空值
空值是Python里一个特殊的值,用
None
表示。
None
不能理解为
0
,因为
0
是有意义的,而
None
是一个特殊的空值。
l  变量
在Python中,等号
=
是赋值语句,可以把任意数据类型赋值给变量,同一个变量可以反复赋值,而且可以是不同类型的变量
理解变量在计算机内存中的表示也非常重要,如写 a = 'ABC'时,Python解释器干了两件事情: 1、在内存中创建了一个'ABC'的字符串;2、在内存中创建了一个名为a的变量,并把它指向'ABC'。
a = 'ABC'
b = a
a = 'XYZ'
print(b)  b的值是’ABC’
l  常量所谓常量就是不能变的变量,比如常用的数学常数π就是一个常量。在Python中,通常用全部大写的变量名表示常量
l  小结
Python支持多种数据类型,在计算机内部,可以把任何数据都看成一个“对象”,而变量就是在程序中用来指向这些数据对象的,对变量赋值就是把数据和变量给关联起来。
对变量赋值x = y是把变量x指向真正的对象,该对象是变量y所指向的。随后对变量y的赋值不影响变量x的指向。
注意:Python的整数没有大小限制,而某些语言的整数根据其存储长度是有大小限制的,例如Java对32位整数的范围限制在-2147483648-2147483647。
Python的浮点数也没有大小限制,但是超出一定范围就直接表示为inf(无限大)。
 

1.2、字符串和编码

l  Python字符串
在最新的Python 3版本中,字符串是以Unicode编码的,也就是说,Python的字符串支持多语言。   
print('包含中文的str')
对于单个字符的编码,Python提供了
ord()
函数获取字符的整数表示,
chr()
函数把编码转换为对应的字符由于Python的字符串类型是
str
,在内存中以Unicode表示,一个字符对应若干个字节。如果要在网络上传输,或者保存到磁盘上,就需要把
str
变为以字节为单位的
bytes
。Python对
bytes
类型的数据用带
b
前缀的单引号或双引号表示
要注意区分
'ABC'
b'ABC'
,前者是
str
,后者虽然内容显示得和前者一样,但
bytes
的每个字符都只占用一个字节
以Unicode表示的
str
通过
encode()
方法可以编码为指定的
bytes
,例如
反过来,如果我们从网络或磁盘上读取了字节流,那么读到的数据就是
bytes
。要把
bytes
变为
str
,就需要用
decode()
方法
l  格式化
%
运算符就是用来格式化字符串的。

l  小结Python 3的字符串使用Unicode,直接支持多语言。当
str
bytes
互相转换时,需要指定编码。最常用的编码是
UTF-8
。Python当然也支持其他编码方式,比如把Unicode编码成
GB2312

>>> '中文'.encode('gb2312')
b'\xd6\xd0\xce\xc4'
但这种方式纯属自找麻烦,如果没有特殊业务要求,请牢记仅使用
UTF-8
编码。

1.3、list 和 tuple

l  List:(可以使用list来模拟堆栈和队列
Python内置的一种数据类型是列表:list。list是一种有序的集合,可以随时添加和删除其中的元素。
追加元素: List.append(‘xxx’)   
插入元素:list.insert(1,’xxxx’)   
删除元素:list.pop(i)删除索引为i的元素。
替换元素: list(i)=’xxxx’
 
l  Tuple:元组
tuple和list非常类似,但是tuple一旦初始化就不能修改,因为tuple不可变,所以代码更安全
看一个“可变的”tuple:t = ('a','b',['A','B'])  t[2][0]=’X’   t变为('a','b',['X','B'])
变得是list的元素,tuple指向的list没有变
l  小结
list和tuple是Python内置的有序集合,一个可变,一个不可变。根据需要来选择使用它们。

1.4、dict和set

 
Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。
这种key-value存储方式,在放进去的时候,必须根据key算出value的存放位置,这样,取的时候才能根据key直接拿到value。
一个key只能对应一个value,如果key不存在,dict就会报错;
要避免key不存在的错误,有两种办法,一是通过
in
判断key是否存在,(注意:返回
None
的时候Python的交互环境不显示结果。)
二是通过dict提供的
get()
方法,如果key不存在,可以返回
None
,或者自己指定的value:
要删除一个key,用
pop(key)
方法,对应的value也会从dict中删除:
dict是用空间来换取时间的一种方法。
dict的key必须是不可变对象要保证hash的正确性,作为key的对象就不能变。在Python中,字符串、整数等都是不可变的,因此,可以放心地作为key。而list是可变的,就不能作为key
 

l  set

set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key。要创建一个set,需要提供一个list作为输入集合set可以看成数学意义上的无序和无重复元素的集合,因此,两个set可以做数学意义上的交集、并集等操作
l  不可变对象

所以,对于不变对象来说,调用对象自身的任意方法,也不会改变该对象自身的内容。相反,这些方法会创建新的对象并返回,这样,就保证了不可变对象本身永远是不可变的。
 

函数

2.1 函数调用

l  小结定义函数时,需要确定函数名和参数个数;如果有必要,可以先对参数的数据类型做检查;函数体内部可以用
return
随时返回函数结果;函数执行完毕也没有
return
语句时,自动
return None
。函数可以同时返回多个值,但其实就是一个tuple。
 

2.2函数的参数

Python的函数定义非常简单,但灵活度却非常大。除了正常定义的必选参数(位置参数)外,还可以使用默认参数、可变参数和关键字参数,使得函数定义出来的接口,不但能处理复杂的参数,还可以简化调用者的代码。

l  默认参数

定义默认参数要牢记一点:默认参数必须指向不变对象!

l  可变参数

可变参数就是传入的参数个数是可变的,可以是1个、2个到任意个,还可以是0个。      
定义可变参数和定义一个list或tuple参数相比,仅仅在参数前面加了一个
*
号。在函数内部,参数
numbers
接收到的是一个tuple,因此,函数代码完全不变。但是,调用该函数时,可以传入任意个参数,包括0个参数:
所以Python允许你在list或tuple前面加一个
*
号,把list或tuple的元素变成可变参数传进去。
def calc(*numbers):xxxxx
>>>nums = [1,2,3]
>>>calc(*nums)

l  关键字参数

可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。
def person(name,age,**kw):
   print('name:',name,'age:',age,'other:',kw)
>>>extra = {'city': 'Beijing','job': 'Engineer'}
>>>person('Jack',24,**extra)
name: Jack age:24 other: {'city': 'Beijing','job': 'Engineer'}
**extra
表示把
extra
这个dict的所有key-value用关键字参数传入到函数的
**kw
参数,
kw
将获得一个dict,注意
kw
获得的dict是
extra
的一份拷贝,对
kw
的改动不会影响到函数外的
extra

l  命名关键字参数

def person(name,age,*,city,job):
   print(name,age,city,job)
 
和关键字参数
**kw
不同,命名关键字参数需要一个特殊分隔符
*
*
后面的参数被视为命名关键字参数。
如果函数定义中已经有了一个可变参数,后面跟着的命名关键字参数就不再需要一个特殊分隔符
*
了:
defperson(name,age,*args,city,job):
   print(name,age,args,city,job)
命名关键字参数必须传入参数名,这和位置参数不同。如果没有传入参数名,调用将报错:

l  参数组合

在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这5种参数都可以组合使用。但是请注意,参数定义的顺序必须是:必选参数、默认参数、可变参数、命名关键字参数和关键字参数。

小结

Python的函数具有非常灵活的参数形态,既可以实现简单的调用,又可以传入非常复杂的参数。默认参数一定要用不可变对象,如果是可变对象,程序运行时会有逻辑错误!要注意定义可变参数和关键字参数的语法:
*args
是可变参数,args接收的是一个tuple;
**kw
是关键字参数,kw接收的是一个dict。以及调用函数时如何传入可变参数和关键字参数的语法:可变参数既可以直接传入:
func(1,2,3)
,又可以先组装list或tuple,再通过
*args
传入:
func(*(1,2,3))
;关键字参数既可以直接传入:
func(a=1,b=2)
,又可以先组装dict,再通过
**kw
传入:
func(**{'a': 1,'b': 2})
。使用
*args
**kw
是Python的习惯写法,当然也可以用其他参数名,但最好使用习惯用法。命名的关键字参数是为了限制调用者可以传入的参数名,同时可以提供默认值。定义命名的关键字参数在没有可变参数的情况下不要忘了写分隔符
*
,否则定义的将是位置参数。

3  高级特性

3.1切片

L = list(range(100))
请写出:L[:10]   L[2:10]   L[:10:2]    L[:]     L[: : 5]
tuple也是一种list,唯一区别是tuple不可变。因此,tuple也可以用切片操作,只是操作的结果仍是tuple:
>>> (0,1,2,3,4,5)[:3]
(0,1,2)
字符串
'xxx'
也可以看成是一种list,每个元素就是一个字符。因此,字符串也可以用切片操作,只是操作结果仍是字符串:
>>> 'ABCDEFG'[::2]
'ACEG'

3.2 迭代

如果给定一个list或tuple,我们可以通过
for
循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration)。List,tuple,dict对象均可迭代。
默认情况下,dict迭代的是key。如果要迭代value,可以用
for value in d.values()
,如果要同时迭代key和value,可以用
for k,v in d.items()

如何判断一个对象是可迭代对象呢?方法是通过collections模块的Iterable类型判断:
from[code] collections
import
Iterable
isinstance(
'abc'
,Iterable)
# str是否可迭代[/code]如果要对list实现类似Java那样的下标循环怎么办?Python内置的(枚举)
enumerate
函数可以把一个list变成索引-元素对,这样就可以在
for
循环中同时迭代索引和元素本身:
for[code] i,value
in
enumerate([
'A'
,
'B'
,
'C'
]):
... [code]    print(i,value)

3.3 列表生成式

列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式。如:list(range(1,11))
For循环前,写元素表达式,For循环后,还可以加上if判断
>>> [code][x * x
for
x
in
range(
1
,
11
)
if
x% 
2
==
0
]
[
4
,
16
,
36
,
64
,
100
]
还可以使用两层循环,可以生成全排列:
>>> [code][m + n
for
m
in'ABC'for
n
in'XYZ'
]
[
'AX'
,
'AY'
,
'AZ'
,
'BX'
,
'BY'
,
'BZ'
,
'CX'
,
'CY'
,
'CZ'
]
import os # 导入os模块,模块的概念后面讲到
>>>[d for d in os.listdir('.')] # os.listdir可以列出文件和目录
 
 
for
循环其实可以同时使用两个甚至多个变量,比如
dict
items()
可以同时迭代key和value
>>>d = {'x': 'A','y': 'B','z': 'C' }
>>>[k + '=' + v for k,v in d.items()]
['y=B','x=A','z=C']
最后把一个list中所有的字符串变成小写:
>>>L = ['Hello','World','IBM','Apple']
>>>[s.lower()for s in L]  #小写    /////        [s.upper()for s in L]   #大写
['hello','world','ibm','apple']
使用内建的
isinstance
函数可以判断一个变量是不是字符串:isinstance(x,str)

3.4 生成器

如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
只要把一个列表生成式的
[]
改成
()
,就创建了一个generator
g = (x *xforx inrange(10))
>>>g
<generatorobject <genexpr> at 0x1022ef630>
可以通过
next()
函数获得generator的下一个返回值。一次次调用next()太变态,正确的方法是使用
for
循环,因为generator也是可迭代对象
generator非常强大。如果推算的算法比较复杂,用类似列表生成式的
for
循环无法实现的时候,还可以用函数来实现。如斐波那契数列。
        
要把
fib
函数变成generator,只需要把
print(b)
改为
yield b
就可以了:
这就是定义generator的另一种方法。如果一个函数定义中包含
yield
关键字,那么这个函数就不再是一个普通函数,而是一个generator:
这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到
return
语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用
next()
的时候执行,遇到
yield
语句返回,再次执行时从上次返回的
yield
语句处继续执行。

3.5 迭代器

凡是可作用于
for
循环的对象都是
Iterable
类型;可以被
next()
函数调用并不断返回下一个值的对象称为迭代器:
Iterator
。它们表示一个惰性计算的序列;生成器都是
Iterator
对象,集合数据类型如
list
dict
str
等是
Iterable
但不是
Iterator
,不过可以通过
iter()
函数获得一个
Iterator
对象。Python的
for
循环本质上就是通过不断调用
next()
函数实现的,例如

4、函数式编程

函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。

高阶函数

l  函数本身也可以赋值给变量,即:变量可以指向函数。
l  那么函数名是什么呢?函数名其实就是指向函数的变量!
l  传入函数:既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
小结把函数作为参数传入,这样的函数称为高阶函数,函数式编程就是指这种高度抽象的编程范式。

Map/reduce

所以,
map()
作为高阶函数,事实上它把运算规则抽象了,因此,我们不但可以计算简单的f(x)=x2,还可以计算任意复杂的函数,比如,把这个list所有数字转为字符串:>>> list(map(str,[1,2,3,4,5,6,7,8,9]))
['1','2','3','4','5','6','7','8','9']
 
reduce
的用法。
reduce
把一个函数作用在一个序列
[x1,x2,x3,...]
上,这个函数必须接收两个参数,
reduce
把结果继续和序列的下一个元素做累积计算,其效果就是
reduce(f,[x1,x2,x3,x4])= f(f(f(x1,x2),x3),x4)
如把序列
[1,3,5,7,9]
变换成整数
13579

>>> from functools import reduce
>>> def fn(x,y):
...    returnx * 10 + y
...
>>> reduce(fn,[1,3,5,7,9])
13579

filter

Python内建的
filter()
函数用于过滤序列。和
map()
类似,
filter()
也接收一个函数和一个序列。和
map()
不同的是,
filter()
把传入的函数依次作用于每个元素,然后根据返回值是
True
还是
False
决定保留还是丢弃该元素。注意到
filter()
函数返回的是一个
Iterator
,也就是一个惰性序列,所以要强迫
filter()
完成计算结果,需要用
list()
函数获得所有结果并返回list。

Sorted 排序函数

Python内置的
sorted()
函数就可以对list进行排序:此外,
sorted()
函数也是一个高阶函数,它还可以接收一个
key
函数来实现自定义的排序,例如按绝对值大小排序:
 
要进行反向排序,不必改动key函数,可以传入第三个参数
reverse=True


 

返回函数

当我们调用
lazy_sum()
时,返回的并不是求和结果,而是求和函数
def lazy_sum(*args):
   defsum():
       ax = 0
       forn in args:
           ax = ax + n
       returnax
   returnsum
 
当我们调用
lazy_sum()
时,每次调用都会返回一个新的函数,即使传入相同的参数:

闭包

注意到返回的函数在其定义内部引用了局部变量
args
,所以,当一个函数返回了一个函数后,其内部的局部变量还被新函数引用,所以,闭包用起来简单,实现起来可不容易。另一个需要注意的问题是,返回的函数并没有立刻执行,而是直到调用了
f()
才执行。返回闭包时牢记一点:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
 

匿名函数

关键字
lambda
表示匿名函数,冒号前面的
x
表示函数参数。匿名函数有个限制,就是只能有一个表达式,不用写
return
,返回值就是该表达式的结果。用匿名函数有个好处,因为函数没有名字,不必担心函数名冲突。此外,匿名函数也是一个函数对象,也可以把匿名函数赋值给一个变量,再利用变量来调用该函数:
#将匿名函数作为返回值
def build(x,y):
   return lambda: x*x+y*y
q=build(5,8)()
print(q)
输出为89.                              

装饰器

假设我们要增强
now()
函数的功能,比如,在函数调用前后自动打印日志,但又不希望修改
now()
函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。本质上,decorator就是一个返回函数的高阶函数。所以,我们要定义一个能打印日志的decorator,可以定义如下:
import[code] functools
deflog(func):
   
@functools.wraps(func)[/code]
   
defwrapper(*args,**kw):[/code]
       print(
'call %s():'
% func.__name__)
       
return
 func(*args,**kw)
   
return
wrapper
 
@log
def now():
   print('2015-3-25')
只需记住在定义
wrapper()
的前面加上
@functools.wraps(func)
即可。

偏函数

        
int()
函数可以把字符串转换为整数,当仅传入字符串时,
int()
函数默认按十进制转换:还提供额外的
base
参数,默认值为
10
。如果传入
base
参数,就可以做N进制的转换:
>>> int('12345',base=8)
5349
>>> int('12345',16)
74565
假设要转换大量的二进制字符串,每次都传入
int(x,base=2)
非常麻烦,于是,我们想到,可以定义一个
int2()
的函数,默认把
base=2
传进去
defint2(x,base=2):
   
return
 int(x,base)
functools.partial
就是帮助我们创建一个偏函数的,不需要我们自己定义
int2()
,可以直接使用下面的代码创建一个新的函数
int2

>>> import functools
>>> int2 = functools.partial(int,base=2)
>>> int2('1000000')
64
>>> int2('1010101')
85
简单总结
functools.partial
的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。
创建偏函数时,实际上可以接收函数对象、
*args
**kw
这3个参数
当函数的参数个数太多,需要简化时,使用
functools.partial
可以创建一个新的函数,这个新函数可以固定住原函数的部分参数,从而在调用时更简单。
 

模块

文件
www.py
的模块名就是
mycompany.web.www
,两个文件
utils.py
的模块名分别是
mycompany.utils
mycompany.web.utils

 自己创建模块时要注意命名,不能和Python自带的模块名称冲突。例如,系统自带了sys模块,自己的模块就不可命名为sys.py,否则将无法导入系统自带的sys模块。

使用内置模块

使用
sys
模块的第一步,就是导入该模块: 导入
sys
模块后,我们就有了变量
sys
指向该模块,利用
sys
这个变量,就可以访问
sys
模块的所有功能。
sys
模块有一个
argv
变量,用list存储了命令行的所有参数。
argv
至少有一个元素,因为第一个参数永远是该.py文件的名称,例如:运行
python3 hello.py
获得的
sys.argv
就是
['hello.py']
;运行
python3 hello.py Michael
获得的
sys.argv
就是
['hello.py','Michael]

 
if __name__=='__main__':
   test()
__name__ 是当前模块名,当模块被直接运行时模块名为 __main__ 。这句话的意思就是,当模块被直接运行时,以下代码块将被运行,当模块是被导入时,代码块不被运行。l  作用域在一个模块中,我们可能会定义很多函数和变量,但有的函数和变量我们希望给别人使用,有的函数和变量我们希望仅仅在模块内部使用。在Python中,是通过
_
前缀来实现的。类似
_xxx
__xxx
这样的函数或变量就是非公开的(private),不应该被直接引用,比如
_abc
__abc
等; 

6、面向对象编程

 所以,面向对象的设计思想是抽象出Class,根据Class创建Instance。面向对象的抽象程度又比函数要高,因为一个Class既包含数据,又包含操作数据的方法。 
数据封装、继承和多态是面向对象的三大特点,我们后面会详细讲解。
 

类和实例

class Student(object):
   pass
class
后面紧接着是类名,即
Student
,类名通常是大写开头的单词,紧接着是
(object)
,表示该类是从哪个类继承下来的,继承的概念我们后面再讲,通常,如果没有合适的继承类,就使用
object
类,这是所有类最终都会继承的类。
bart =Student()               创建实例是通过类名+()实现的
 
由于类可以起到模板的作用,因此,可以在创建实例的时候,把一些我们认为必须绑定的属性强制填写进去。通过定义一个特殊的
__init__
方法,在创建实例的时候,就把
name
score
等属性绑上去:

注意到
__init__
方法的第一个参数永远是
self
,表示创建的实例本身,因此,在
__init__
方法内部,就可以把各种属性绑定到
self
,因为
self
就指向创建的实例本身。
 

数据封装

面向对象编程的一个重要特点就是数据封装。在上面的
Student
类中,每个实例就拥有各自的
name
score
这些数据。我们可以通过函数来访问这些数据,比如打印一个学生的成绩:>>>bart.print_score()BartSimpson: 59方法就是与实例绑定的函数,和普通函数不同,方法可以直接访问实例的数据;通过在实例上调用方法,我们就直接操作了对象内部的数据,但无需知道方法内部的实现细节。print(lisa.name,lisa.get_grade())
print(bart.name,bart.get_grade())
和静态语言不同,Python允许对实例变量绑定任何数据,也就是说,对于两个实例变量,虽然它们都是同一个类的不同实例,但拥有的变量名称都可能不同:

 

6.2 访问限制

但是,从前面Student类的定义来看,外部代码还是可以自由地修改一个实例的
name
score
属性:
如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线
__
,在Python中,实例的变量名如果以
__
开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问

 
双下划线结尾变量:变量名类似
__xxx__
的是特殊变量,特殊变量是可以直接访问的,不是private变量,所以,不能用
__name__
__score__
这样的变量名
单下划线变量:比如
_name
,这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”
双下划线开头的实例变量是不是一定不能从外部访问呢?其实也不是。不能直接访问
__name
是因为Python解释器对外把
__name
变量改成了
_Student__name
,所以,仍然可以通过
_Student__name
来访问
__name
变量

6.3 继承和多态(重难点)

https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001431865288798deef438d865e4c2985acff7e9fad15e3000由运行时该对象的确切类型决定,这就是多态真正的威力:调用方只管调用,不管细节,而当我们新增一种
Animal
的子类时,只要确保
run()
方法编写正确,不用管原来的代码是如何调用的。这就是著名的“开闭”原则:对扩展开放:允许新增
Animal
子类;对修改封闭:不需要修改依赖
Animal
类型的
run_twice()
等函数。

静态语言 vs 动态语言

对于静态语言(例如Java)来说,如果需要传入
Animal
类型,则传入的对象必须是
Animal
类型或者它的子类,否则,将无法调用
run()
方法。对于Python这样的动态语言来说,则不一定需要传入
Animal
类型。我们只需要保证传入的对象有一个
run()
方法就可以了:这就是动态语言的“鸭子类型”,它并不要求严格的继承体系,一个对象只要“看起来像鸭子,走起路来像鸭子”,那它就可以被看做是鸭子。

小结

继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写。动态语言的鸭子类型特点决定了继承不像静态语言那样是必须的。

6.4 获取对象信息

当我们拿到一个对象的引用时,如何知道这个对象是什么类型、有哪些方法呢?l  使用type()l 使用isinstance() 总是优先使用isinstance()判断类型,可以将指定类型及其子类“一网打尽”。l 使用dir():获得一个对象的所有属性和方法,可以使用
dir()
函数,它返回一个包含字符串的list,类似
__xxx__
的属性和方法在Python中都是有特殊用途的,比如
__len__
方法返回长度。剩下的都是普通属性或方法,

小结

通过内置的一系列函数,我们可以对任意一个Python对象进行剖析,拿到其内部的数据。要注意的是,只有在不知道对象信息的时候,我们才会去获取对象信息。

6.5 实例属性和类属性

在编写程序的时候,千万不要对实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性   
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: