python中基本语法

#输入语句:
>>> print'100+100=%d' %(100+100)
100+100=200

#输出语句
>>> name = raw_input('input your name:')
input your name:yinheyi
>>> print('hello,%s' %name)
hello,yinheyi

 

注意:raw_input()语句接收以后,默认保存为str格式哦,如果要比较大小的话,记得转为int类型。

 

>>> number = raw_input('input a number:')
input a number:12
>>> type(number)
<type 'str'>
>>> number = int(raw_input('input a number:'))
input a number:12
>>> type(number)
<type 'int'>

 

 

判断与循环语句:

判断语句:if…elif…else

 

>>> if a>= 50:
...     print 'the number is big'
... elif a < 50:
...     print'the number is small'
... else:
...     print "i don't know"
... 
the number is big

 

循环语句: for…in

>>> sum = 0
>>> for number in range(101):
...     sum = sum + number
... 
>>> print sum
5050

循环语句: while

 

>>> sum = 0
>>> n = 1
>>> while n < 101:
...     sum = sum + n
...     n = n + 1
... 
>>> print sum
5050

 

 

数据类型:列表、元组、字典、set

list: Python内置的一种数据类型是列表。lists是一个有序的集合,可以添加与删除元素。

生成它是用  []  就可以啦;

调用它时,用下标调用就可以啦(从0开始);如第一个元素,list[0];倒数第一个,list[-1];

可以用len()函数获得list元素的个数;

在尾部添加用append(), 中间插入用insert();尾部删除用pop();指定位置删除为pop(i);

 

#定义一个friends的列表
>>> friends = ['xiaoming','ergou','sanmao']
>>> friends
['xiaoming', 'ergou', 'sanmao']
>>> friends[0]
'xiaoming'
>>> friends[-1]
'sanmao'

#添加与删除
>>> friends.append('dapeng')
>>> friends
['xiaoming', 'ergou', 'sanmao', 'dapeng']
>>> friends.insert(0,'diyi')
>>> friends
['diyi', 'xiaoming', 'ergou', 'sanmao', 'dapeng']

>>> friends.pop()
'dapeng'
>>> friends
['diyi', 'xiaoming', 'ergou', 'sanmao']
>>> friends.pop(2)
'ergou'
>>> friends
['diyi', 'xiaoming', 'sanmao']

#替换
>>> friends[0] = 'wangbadan'
>>> friends
['wangbadan', 'xiaoming', 'sanmao']

 

元组(tuple):tuple和list非常类似,但是tuple一旦初始化就不能修改。只要记住它不能修改就可以啦。很安全。

用 () 定义啊。

用下标调用,即tuple[1];

注意:它定义一个元素的tuple时,一定要这样写,如:name = (‘yin’,), 千万别写成 name = (‘yin’);

 

name = ('zhai','yin')
>>> name
('zhai', 'yin')
>>> name[0]
'zhai'
>>> name[-1]
'yin'

 

 

字典(dictionary):它就是键-值对。如在C++语言中为map的容器。它的特点就是可以快速查找,需要占用大量的内存,内存浪费多。通过key计算位置的算法称为哈希算法(Hash)。

用 {} 定义dictionary哦;

随着dictionary的增加,查找时间不会增加的。

多次对一个key放入value,后面的值会把前面的值冲掉:

可以用  ‘key’in dic 或 dic.get(‘key’)的方法来查看key是否存在。注意:dict提供的get方法,如果key不存在,可以返回None,或者自己指定的value,返回None的时候Python的交互式命令行不显示结果。

删除用: pop(key)。添加时,直接用key值的索引添加就可以的。

注意:ict内部存放的顺序和key放入的顺序是没有关系的。

 

#定义一个dictionary;
score = {'xiaoming':85,'xiaohong':62}
>>> score
{'xiaoming': 85, 'xiaohong': 62}

#添加一个元素;
>>> score['wangdan'] = 85
>>> score
{'xiaoming': 85, 'xiaohong': 62, 'wangdan': 85}

#删除一个元素;
>>> score.pop('xiaohong')
62
>>> score
{'xiaoming': 85, 'wangdan': 85}

#查看key是否存在;
>>> 'xiaoming' in score
True

#查看一个key对应的值;
>>> score.get('wangdan')
不存在时,返回一个自定义的值;
85>>> score.get('hehehe',-1)
-1

 

 

set:set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key。set和dict的唯一区别仅在于没有存储对应的value,但是,set的原理和dict一样,所以,同样不可以放入可变对象。

要创建一个set,需要提供一个list作为输入集合:

通过add(key)与remove(key)添加与删除元素;

 

>>> s = set([1, 2, 3])
>>> s
set([1, 2, 3])

注意,传入的参数[1, 2, 3]是一个list,而显示的set([1, 2, 3])只是告诉你这个set内部有1,2,3这3个元素,显示的[]不表示这是一个list。

重复元素在set中自动被过滤:

>>> s = set([1, 1, 2, 2, 3, 3])
>>> s
set([1, 2, 3])

添加与删除

 

>>> s = set([1,2,3])
>>> s
set([1, 2, 3])
>>> s.add('xiaoming')
>>> s
set([1, 2, 3, 'xiaoming'])
>>> s.add(0)
>>> s
set([0, 1, 2, 3, 'xiaoming'])
>>> s.remove(2)
>>> s
set([0, 1, 3, 'xiaoming'])

 

 

 

对于list与tuple的切片操作:

如list[:5]或list[0:5]表示第0,1,2,3,4个索引值;当然也可以为负的如,list[-2:0]等于list[-2:]即倒数第2、倒数第1个数;也可以跳着来哦:list[1:10:2],表示步长为2的。

 

list=range(100)
#正着切片
>>> list[:10]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
#负索引切片
 list[-10:]
[90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
#倒着切片
>>> list[10:0:-1]
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
>>> list[-1:-10:-1]
[99, 98, 97, 96, 95, 94, 93, 92, 91]
#跳着切片
>>> list[::10]
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90]

 

 

 

#tuple的切片
>>> (0, 1, 2, 3, 4, 5)[:3]
(0, 1, 2)
#字符串的切片
>>> 'ABCDEFG'[:3]
'ABC'
>>> 'ABCDEFG'[::2]
'ACEG'

 

 

它的迭代:

对于list、tuple还有字符串都可以用 for…in 进行迭代哦;

而对于dictionary的话,也可以哦,只不过默认情况下,dict迭代的是key。如果要迭代value,可以用for value in d.itervalues(),如果要同时迭代key和value,可以用for k, v in d.iteritems()

那么,如何判断一个对象是可迭代对象呢?方法是通过collections模块的Iterable类型判断:

另外:Python内置的enumerate函数可以把一个list、tuple、字符串本身变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身:

 

>>> from collections import Iterable
>>> isinstance('abc', Iterable) # str是否可迭代
True
>>> isinstance([1,2,3], Iterable) # list是否可迭代
True
>>> isinstance(123, Iterable) # 整数是否可迭代
False

 

 

列表生成式:很牛逼很方便的;它是用来创建list的生成式;我们举例子看看哈:

生成1-10的list:

>>> range(1,11)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

生成 12、22、……102的list:

>>> list = [x*x for x in range(1,11)]
>>> list
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

还可以再选择一下哦:

>>> [x * x for x in range(1, 11)if x % 2 == 0] [4, 16, 36, 64, 100]

还可以两层循环的:

>>> [m + n for m in 'ABC' for n in 'XYZ'] ['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']

 

生成器:

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。

所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器(Generator)。

创建方法1:第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:

>>> L = [x * x for x in range(10)]
>>> L
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> g = (x * x for x in range(10))
>>> g
<generator object <genexpr> at 0x104feab40>

可以通过generator的.next()方法打印出来数据,另外也可以通过迭代哦,基本上我们都选择for…in迭代方法。

 

创建方法2:通过特殊函数创建:如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator。

 

#这是函数,输出斐波那契数列
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        print b
        a, b = b, a + b
        n = n + 1

#这是generator,也是生成斐波那契数列;
def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1

 

 

注意:这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

 

>>> def odd():
...     print 'step 1'
...     yield 1
...     print 'step 2'
...     yield 3
...     print 'step 3'
...     yield 5
...
>>> o = odd()
>>> o.next()
step 1
1
>>> o.next()
step 2
3
>>> o.next()
step 3
5
>>> o.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

函数的定义:

使用def语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回。

当用return 返回多个值时,返回的其实是一个tuple,即元组。

当一个语句块是什么也不做时,请用pass语句,如果为空的话,分出错的。

如果函数没有return或者只有单单的一个reuturn时 , 则返回none。

>>> def sum(x, y):
...     sum = x + y
...     return sum
... 
>>> print sum(1,2)
3

函数的参数问题:

函数可以有默认的参数:且函数的默认参数必须指向不变的对象(否则有逻辑错误)。

复制代码

>>> def sum(x=1, y=2):
...     return x + y
... 
>>> print sum()
3
>>> print sum(5)
7
>>> print sum(y=10)
11

复制代码

函数的可变参数:定义可变参数和定义list或tuple参数相比,仅仅在参数前面加了一个*号。在函数内部,参数numbers接收到的是一个tuple,因此,函数代码完全不变。但是,调用该函数时,可以传入任意个参数,包括0个参数。另外,Python允许你在list或tuple前面加一个*号,把list或tuple的元素变成可变参数传进去。

复制代码

#可变参数;
>>> def sum(*numbers):
...     sum = 0
...     for num in numbers:
...             sum = sum + num
...     return sum
... 
>>> sum(1,2,3)
6
>>> sum(1,2,3,4,5,6)
21

#把list或tuple元素变为可变参数传入
>>> list = [1,2,3,4,5,6,7,8]
>>> sum(*list)
36
>>> tuple = (1,3,4,75)
>>> sum(*tuple)
83

复制代码

关键字参数:它也是可变的,仅仅在参数前面加了两个*号。这些关键字参数在函数内部自动组装为一个dict,Python允许你dictionary前面加**号,把dictionary元素变成可变参数传进去。。

复制代码

>>> def person(name, age, **other):
...     print 'name:',name,'\n'\
...           'age:',age,'\n'\
...           'other:',other
... 
>>> person('xiaoming',18,sex='boy')
name: xiaoming 
age: 18 
other: {'sex': 'boy'}

复制代码

#把dictionar元素参数传入
>>> dic = {'sex':'boy','tall':174}
>>> person('xiaohong',22,**dic)
name: xiaohong 
age: 22 
other: {'tall': 174, 'sex': 'boy'}

参数可以组合使用:在Python中定义函数,可以用必选参数、默认参数、可变参数和关键字参数,这4种参数都可以一起使用,或者只用其中某些,但是请注意,参数定义的顺序必须是:必选参数、默认参数、可变参数和关键字参数。

 

另外,对于对于任意函数,都可以通过类似func(*list, **dictionary)的形式调用它,无论它的参数是如何定义的。

 

对于递归函数:优点是定义简单,逻辑清晰。但是有一个问题,使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。

 

高阶函数:就是能接收其它函数作为参数的函数。

复制代码

#定义一个简单的高阶函数:
>>> def add(x, y, f):
...     return f(x) + f(y)

#定义一个函数:
 def square(x):
...     return x * x

#調用高阶函数:
>>> add(5,6,square)
61

复制代码

 

map()高阶函数

map()函数接收两个参数,一个是函数,一个是序列,map将传入的函数依次作用到序列的每个元素,并把结果作为新的list返回。

复制代码

#map函数分别用函数对传入的元素做处理哦
>>> def square(x):
...     return x*x
>>> list = range(1,6)
>>> list
[1, 2, 3, 4, 5]
>>> map(square, list)
[1, 4, 9, 16, 25]

复制代码

 

reduce()高阶函数

reduce把一个函数作用在一个序列[x1, x2, x3...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是:reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4).

复制代码

#看看reduce,把[1, 2, 3, 4, 5] 变为 一个数:12345
>>> list
[1, 2, 3, 4, 5]
>>> def func(x, y):
...     return x*10 + y
... 
>>> reduce(func, list)
12345

复制代码

 

filter()高阶函数:

filter()函数用于过滤序列。接收一个函数和一个序列。filter()把传入的函数依次作用于每个元素,然后根据返回值是True还是False决定保留还是丢弃该元素。

def is_odd(n):
    return n % 2 == 1

filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15])
# 结果: [1, 5, 9, 15]

排序算法:sorted()函数

通常规定,对于两个元素xy,如果认为x < y,则返回-1,如果认为x == y,则返回0,如果认为x > y,则返回1,这样,排序算法就不用关心具体的比较过程,而是根据比较结果直接排序。

>>> sorted([123,34,654,24,623342,4546,32,0])
[0, 24, 32, 34, 123, 654, 4546, 623342]

 

另外,它也可以接收一个函数,用于自定义的排序。

复制代码

#定义一个倒序
>>> def reversed_cmp(x, y):
...     if x > y:
...         return -1
...     if x < y:
...         return 1
...     return 0
... 

>>> sorted([123,34,654,24,623342,4546,32,0],reversed_cmp)
[623342, 4546, 654, 123, 34, 32, 24, 0]

复制代码

 

 

返回函数这个变量:可以在一个函数里面在定义一个一个函数,并返回这个函数名。

内部函数可以引用外部函数的参数和局部变量,当内部函数名被返回时,外部函数的相关参数和变量都保存在返回的函数中,这种称为“闭包(Closure)”的程序结构拥有极大的威力。

来,举例说明:

复制代码

>>> def sum(x, y):
...     def sum1():
...             return x + y
...     return sum1

>>> f = sum(1, 2)
>>> f
<function sum1 at 0x7fab499ec8c0> #可以看出 f 为一个函数变量哦;
>>> f()     #返回这个函数的值;
3

复制代码

看下面两个程序,仔细体会哦:

复制代码

>>> def func1():
...     i = 1
...     def func2():
...             return i * i
...     return func2
... 
>>> f = func1()
>>> f()
1

复制代码

复制代码

>>> def func1():
...     i = 1
...     def func2():
...             return i * i
...     i = 5
...     return func2
... 
>>> f = func1()
>>> f()
25

复制代码

看到了吧,返回的函数没有立刻执行,而是直到调用了f()才执行。当执行时,i 变为了5。

返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。

 

我们可以这样做,让它保证不受影响,这样做的原因是因为已经把函数func2()的参数绑定了哦,为1。

复制代码

>>> def func1():
...     i = 1
...     def func2(i):
...             def func3():
...                     return i * i
...             return func3
...     return func2(i)
...     i = 5
... 
>>> f = func1()
>>> f()
1

复制代码

 

匿名函数:有些时候,不需要显式地定义函数,直接传入匿名函数更方便。

关键字lambda表示匿名函数,匿名函数有个限制,就是只能有一个表达式,返回值就是该表达式的结果。

下面见识一下匿名函数哦:

>>> list = range(1,11)
>>> list
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> map(lambda x: x*x ,list)
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

 

函数装饰器:

就是说,我们想对一个函数进行增强一些功能,但是呢,我们又不修改函数的定义,这种在代码运行期间动态增加功能的方式,称之为“装饰器”(Decorator)。本质上,decorator就是一个返回函数的高阶函数。

 

一些额外的知识:函数对象都有一个__name__的属性,可以得到函数名字。如:

复制代码

>>> def hello():
...     print 'hello,world'
... 
>>> f = hello
>>> hello.__name__
'hello'
>>> f.__name__
'hello'

复制代码

 

看看下面实现的decorator:

复制代码

#定义了一个函数的decorator;
def f1(func):
        def f2(x, y): 
                print 'i am using decorator'
                print 'call %s ' %func.__name__
                return func(x, y)
        return f2


#用 @ 语法,把decorator置于函数的定义处,即邦定函数哦;
@f1
def sum(x,y):
        return x + y 

#调用它:
print sum(2,3)

复制代码

输出为:

i am using decorator
call sum 
5

这是的@f1,就相当于 sum = f1(sum);

 

再看一个哈,我们可以给decorator传入一定的参数哦:

复制代码

# 定义一个函数的decorator;
def f1(name):
        def f2(func):
                def f3(x, y): 
                        print 'my name is %s' %name
                        print 'i am using decorator'
                        print 'call %s ' %func.__name__
                        return func(x, y)
                return f3
        return f2

#用 @语法哦;
@f1('yinheyi')
def sum(x,y):
        return x + y 

#调用它
print sum(2,3)

复制代码

输出为:

my name is yinheyi
i am using decorator
call sum 
5

 

这是的@f1('yinheyi') 相当于 sum = f1('yinheyi') (sum);

 

对于上面的操作还有一些小问题:

上面的sum.__func__ 变为了f3,而不再是sum。所以:需要把原始函数sum的__name__等属性复制到f3函数中,否则,有些依赖函数签名的代码执行就会出错。

Python内置的functools.wraps就是干这个事的,所以, 在加入这个一句就可以啦:具体如下:

复制代码

# 添加这个库
import functools

def f1(name):
        def f2(func):
                @functools.wraps(func)    #加入这个一个语句哦;
                def f3(x, y): 
                        print 'my name is %s' %name
                        print 'i am using decorator'
                        print 'call %s ' %func.__name__
                        return func(x, y)
                return f3
        return f2


@f1('yinheyi')
def sum(x,y):
        return x + y 
print sum(2,3)
print 'the name of sum is \'%s\'' %sum.__name__

复制代码

输出为:

my name is yinheyi
i am using decorator
call sum 
5
the name of sum is 'sum'

偏函数:functools.partial帮助我们创建一个偏函数。它的作用为:把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。

举例说明,如int()函数,它可以把字符串转换为整数,加外,它还提供了额外的base参数,如果传入base参数,就可以做N进制的转换。如:

int('12345', base=8)
5349

 

当我们想假设要转换大量的二进制字符串,每次都传入int(x, base=2)非常麻烦,于是,我们想到,可以定义一个int2()的函数,默认把base=2传进去:

def int2(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的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。

注意到上面的新的int2函数,仅仅是把base参数重新设定默认值为2,但也可以在函数调用时传入其他值:

>>> int2('1000000', base=10)
1000000

模块:在Python中,一个.py文件就称之为一个模块(Module)。

为了避免模块名冲突,Python又引入了按目录来组织模块的方法,称为包(Package)。例如两个名不hello.py的模块分别在china的包和school里的包里,然后呢,现在它们的名字分别为:china.hello与school.hello, 这样就不冲突了吧。

每一个包目录下面都会有一个__init__.py的文件,这个文件是必须存在的,否则,Python就把这个目录当成普通目录,而不是一个包。

 

自己写一个模块:(主要学习它的格式),创建一个hello.py的文件,内容如下:

复制代码

1 #!/usr/bin/python                                                     
  2 # -*- coding: utf-8 -*-
  3 
  4 'this is a hello module, i am coming '
  5 __author__='yinheyi'
  6 
  7 import sys
  8 
  9 def test():
 10         args = sys.argv
 11         if len(args) == 1:
 12                 print 'hello,world'
 13                 print '你好,世界!'
 14         elif len(args) == 2:
 15                 print 'hello,%s' % args[1]
 16         else:
 17                 print '你的参数个数不对啊,我的哥!'
 18 if __name__== '__main__':
 19         test()

复制代码

第2行注释表示.py文件本身使用标准UTF-8编码;

第4行是一个字符串,表示模块的文档注释,任何模块代码的第一个字符串都被视为模块的文档注释;

第5行使用__author__变量把作者写进去,这样当你公开源代码后别人就可以瞻仰你的大名;

注意:

if __name__=='__main__':
    test()

当我们在命令行运行hello模块文件时,Python解释器把一个特殊变量__name__置为__main__,而如果在其他地方导入该hello模块时,则不会置为__main__, 所以我们可以直接运行这个模块哦,用于运行测试。

 

 

 

给模块起一个别名:

import 模块名 as 别名

 

 

模块内的变量与函数的作用域:

在一个模块中,我们可能会定义很多函数和变量,但有的函数和变量我们希望给别人使用,有的函数和变量我们希望仅仅在模块内部使用。在Python中,是通过_前缀来实现的。

正常的函数和变量名是公开的(public),可以被直接引用,比如:abcx123PI等;

类似__xxx__这样的变量是特殊变量,可以被直接引用,但是有特殊用途,比如上面的__author____name__就是特殊变量,hello模块定义的文档注释也可以用特殊变量__doc__访问,我们自己的变量一般不要用这种变量名;

类中,__xxx这样的函数或变量就是非公开的(private),即有__开头的名字;

 

模块的搜索路经:默认情况下,Python解释器会搜索当前目录、所有已安装的内置模块和第三方模块,搜索路径存放在sys模块的path变量中。

如果我们要添加搜索目录,有两种方法,

一是直接修改sys.path,这种方法在退出python后,会失效的。

>>> import sys
>>> sys.path.append('你自己的路经')

二是设置环境变量PYTHONPATH.可以在.bashrc里添加的,如,export PYTHONPATH = ‘目录‘:$PYTHONPATH

 

 

使用__future__模块:比如当我们是python2.7时,而我们想使用python3.4的python的功能时,怎么办呢?我们可以从

__future__模块里,导入我们想要用的功能。如除法:

复制代码

#这是在python2.7中的
>>> 5/3
1
#导入新的;
>>> from __future__ import division
>>> 5/3
1.6666666666666667

复制代码

 

面向对象的编程:它就是把一个对象作为基本单元,这个对象里有数据,也有对数据的操作方法啦。你看看C语言中,是不是以函数 为单元呢??这就是差别。例如一个水杯,它的元素就是水,它可以的操作有加水,倒水等。

面向对象编程的过程很简单,首先创建一个类(其实,我认为就是一个数据类型啦,如int),然后再创建这个类的对象就可以啦。就好像你定义了一个汽车,然后,根据你的定义造出汽车的实例就可以啦。

类的定义,举个例子:

复制代码

#这是从 最根类继承的,旧的方式定义Python类允许不从object类继承,但这种编程方式已经严重不推荐使用。任何时 候,如果没有合适的类可以继承,就继承自object类。 
7 class Car(object):   
  8 #定义一个含有的属性啦;
  9         color_ = ''
 10         weight_ = 0
 11         __wheel_ = 4  #可以通过__开头开定义私有的属性;
 12 #定义它的方法;
 13         def __init__(self, color, weight, wheel):
 14                 self.color_ = color
 15                 self.weight_ = weight
 16                 self.__wheel_ = wheel
 17         def get_color(self):
 18                 return self.color_
 19         def get_weight(self):
 20                 return self.weight_
 21         def get_wheel(self):
 22                 return self.__wheel_
 23 
 24 baoma = Car('red',80,4)
 25 print baoma.get_color()
 26 print baoma.get_weight()
 27 print baoma.get_wheel()

复制代码

输出为:

red
80
4

总结:

类的私有属性:
  __private_attrs  两个下划线开头,声明该属性为私有,不能在类地外部被使用或直接访问。在类内部的方法中使用时 self.__private_attrs
类的方法
  __private_method 两个下划线开头,声明该方法为私有方法,不能在类地外部调用。在类的内部调用slef.__private_methods

有些时候,你会看到以一个下划线开头的实例变量名,比如_name,这样的实例变量外部是可以访问的,但是,按照约定俗成的规定,当你看到这样的变量时,意思就是,“虽然我可以被访问,但是,请把我视为私有变量,不要随意访问”。

双下划线开头的实例变量是不是一定不能从外部访问呢?其实也不是。不能直接访问__name是因为Python解释器对外把__name变量改成了_Student__name,所以,仍然可以通过_Student__name来访问__name变量,但是不同版本的Python解释器可能会把__name改成不同的变量名。

 

在类地内部,使用def关键字可以为类定义一个方法,与一般函数定义不同,类方法必须包含参数self,且为第一个参数私有的类方法
类的专有方法:
__init__  构造函数,在生成对象时调用
__del__   析构函数,释放对象时使用
__repr__ 打印,转换
__setitem__按照索引赋值
__getitem__按照索引获取值
__len__获得长度
__cmp__比较运算
__call__函数调用
__add__加运算
__sub__减运算
__mul__乘运算
__div__除运算
__mod__求余运算
__pow__称方

 

类的继承与多态:我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类、父类或超类

定义一个基类:

class Animal(object):
    def run(self):
        print 'Animal is running...'

定义它的子类:

复制代码

class Tiger(Animal):
    pass
class Dog(Animal):
    def run(self):
        print 'Dog is running...'

class Cat(Animal):
    def run(self):
        print 'Cat is running...'

复制代码

运行:

tiger = Tiger()
tiger.run()
dog = Dog()
dog.run()
cat = Cat()
cat.run()

 

输出:

Animal is running...

Dog is running...
Cat is running...
 
 
多态:要理解多态,你要知道上面的dog与cat的实例同时属于Animal 与Dog 和Cat类型哦;
当我们定义一个函数时,如果传入的数据类型为Animal的话,我们可以把Animal的实例或着继承Anaimal的类的类型传入这个函数中。
看一个例子:定义一个函数:
 
def run_twice(animal):
    animal.run()
    animal.run()
然后呢,当我们传入Animal的实例时,run_twice()就打印出:
>>> run_twice(Animal())
Animal is running...
Animal is running...

 

当我们传入Dog的实例时,run_twice()就打印出:

>>> run_twice(Dog())
Dog is running...
Dog is running...

 

当我们传入Cat的实例时,run_twice()就打印出:

>>> run_twice(Cat())
Cat is running...
Cat is running...

 

可以看出:

对于Animal的子类,不必对run_twice()做任何修改,实际上,任何依赖Animal作为参数的函数或者方法都可以不加修改地正常运行,原因就在于多态。

多态的好处就是,当我们需要传入Dog、Cat、时,我们只需要接收Animal类型就可以了,因为Dog、Cat都是Animal类型,然后,按照Animal类型进行操作即可。由于Animal类型有run()方法,因此,传入的任意类型,只要是Animal类或者子类,就会自动调用实际类型的run()方法,这就是多态的意思:

对于一个变量,我们只需要知道它是Animal类型,无需确切地知道它的子类型,就可以放心地调用run()方法,而具体调用的run()方法是作用在Animal、Dog、Cat对象上,由运行时该对象的确切类型决定,这就是多态真正的威力:调用方只管调用,不管细节,而当我们新增一种Animal的子类时,只要确保run()方法编写正确,不用管原来的代码是如何调用的。

这就是著名的“开闭”原则:

对扩展开放:允许新增Animal子类;

对修改封闭:不需要修改依赖Animal类型的run_twice()等函数。

 
 
获取对象有信息:
判断基本类型都可以用type()函数判断的,如:
>>> type(132)
<type 'int'>
>>> type('lol')
<type 'str'>>>> type([1,2,3])
<type 'list'>
另外,Python把每种type类型都定义好了常量,放在types模块里,使用之前,需要先导入,可以这这样子:

复制代码

>>> import types
>>> type('lol')==types.StringType
True
>>> type([])==types.ListType
True
>>> type(str)==types.TypeType
True

复制代码

对于类的话,可以使用isinstance():
>>> isinstance(dog, Dog)
True

 

使用dir()函数获取类的对象的属性与方法。使用dir()函数,它返回一个包含字符串的list。

复制代码

#看看字符串都有哪些属性与方法
>>> dir('lol')
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__', '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '_formatter_field_name_split', '_formatter_parser', 'capitalize', 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

复制代码

如,如__len__方法返回长度。在Python中,如果你调用len()函数试图获取一个对象的长度,实际上,在len()函数内部,它自动去调用该对象的__len__()方法。

 

然后配合hasattr()getattr()setattr()我们可以直接操作一个对象的状态。

hasattr():判断是否存在某个属性或方法;

getattr():得到是否存在某个属性或方法;

setattr():设置是否存在某个属性或方法;

 

python作为动态语言,有很多的灵活性。

我们可以动态的能已经定义的实例绑属性与方法哦,也可以给一个类绑定方法的。

#给一个实例绑定属性:
>>> class Car():
...     pass
... 
>>> bmw = Car()
>>> bmw.clor = 'red'

 

复制代码

#给一个实例邦定一个方法
>>> def get_color(self):
...     return self.color
... 
>>> from types import MethodType
>>> bmw.color = MethodType(get_color, bmw, Car)
>>> bmw.color()
'red'

复制代码

 

# 给一个类邦定方法
>>> def get_color(self):
...     return self.color
... 
>>> from types import MethodType
>>> Car.color = MethodType(get_color, None, Car)

 

当我们想限制动态绑定的属性的名称时,怎么办呢?那就利用Class的__slots__变量。

为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class能添加的属性:

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

#这样的话,我们的Student只能动态绑定 'name'与‘age'这两个动态变量了。

另外,

使用@property装饰器可以把定义的一个方法,变为通过属性来调用的。

还有,很有一些特殊的变量或方法来定制类,如__len__、__str__、__iter__、__getitem__等等等 ,具体可以用到的时候具体查一下的。

 

python中的错误处理机制:

错误处理机制:try …except…finally

Python的错误其实也是class,所有的错误类型都继承自BaseException。 在python程序中,一旦出现错误的话,它就要一级级的上报,直到某个函数能够处理这个错误,如果最后没有函数可以处理这个错误的话,最后就被python的解释器捕获,打印出错误信息,并退出程序了。

因为错误是一级一级的一报的,所以,不需要在每个可能出错的地方去捕获错误,只要在合适的层次去捕获错误就可以了。

复制代码

1 #!/usr/bin/python                                                     
  2 # -*- coding: utf-8 -*-
  3 
  4 try:
  5         r = 10 /0
  6 except ZeroDivisionError, sh:
  7         print '出现错误了,except:',sh
  8 finally:
  9         print 'finally,错误机制结束'
 10 print 'end,程序结束'

复制代码

输出:

yinheyi@ubuntu:~/python$ ./2.py
出现错误了,except: integer division or modulo by zero
finally,错误机制结束
end,程序结束

 

我们也可以利用python中的log模块记录错误信息,然后分析错误原因。我们在except下面加入了一个记录错误的语句:

复制代码

1 #!/usr/bin/python                                                     
  2 # -*- coding: utf-8 -*-
  3 import logging
  4 try:
  5         r = 10 /0
  6 except ZeroDivisionError, sh:
  7         print '出现错误了,except:',sh
  8         logging.exception(sh)
  9 finally:
 10         print 'finally,错误机制结束'
 11 print 'end,程序结束'

复制代码

它的输出为:

复制代码

yinheyi@ubuntu:~/python$ ./2.py
出现错误了,except: integer division or modulo by zero
ERROR:root:integer division or modulo by zero
Traceback (most recent call last):
  File "./2.py", line 5, in <module>
    r = 10 /0
ZeroDivisionError: integer division or modulo by zero
finally,错误机制结束
end,程序结束

复制代码

 

可以用raise抛出错误的,错误也可以自己定义的哦,具体,等着我用到了,我再补冲哈

另外,还有和程序的调试,测试啦等待,现在暂时用不着,不写了就哈。(用于的时候学习代码是效率最高的)

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值