python grammar tips

记录一些python中的基本语法知识点(主要是2.7版本的),总是忘记。

基本类型

布尔值可以用and、or和not运算。and运算是与运算。

or运算是或运算

not运算是非运算

空值是Python里一个特殊的值,用None表示。None不能理解为0,因为0是有意义的,而None是一个特殊的空值

非强类型语言
这种变量本身类型不固定的语言称之为动态语言,与之对应的是静态语言。静态语言在定义变量时必须指定变量类型,如果赋值的时候类型不匹配,就会报错

常量表示
所谓常量就是不能变的变量,比如常用的数学常数π就是一个常量。在Python中,通常用全部大写的变量名表示常量

Python支持多种数据类型,在计算机内部,可以把任何数据都看成一个“对象”,而变量就是在程序中用来指向这些数据对象的,对变量赋值就是把数据和变量给关联起来。

编码 格式化输出

在Python中,采用的格式化方式和C语言是一致的,用占位符%实现,%d整数
%f 浮点数 %s 字符串 %x 十六进制整数

Python在后来添加了对Unicode的支持,以Unicode表示的字符串用u’…’表示

基本结构

list采用中括号 python内置的一种数据类型是列表:list。list是一种有序的集合,可以随时添加和删除其中的元素

tuple采用小括号 另一种有序列表叫元组:tuple。tuple和list非常类似,但是tuple一旦初始化就不能修改,只有1个元素的tuple定义时必须加一个逗号,,来消除歧义。

list和tuple是Python内置的有序集合,一个可变,一个不可变

dict类型

1
2
3
>>> d = {'Michael': 95, 'Bob': 75, 'Tracy': 85}
>>> d['Michael']
95

避免key-value不存在的方式,一是通过in判断key是否存在:

1
2
>>> 'Thomas' in d
False

二是通过dict提供的get方法,如果key不存在,可以返回None,或者自己指定的value,get方法就是说,如果key不存在的话,就返回-1。

1
2
3
>>> d.get('Thomas')
>>> d.get('Thomas', -1)
-1

要删除一个key,用pop(key)方法,对应的value也会从dict中删除:

1
2
3
4
>>> d.pop('Bob')
75
>>> d
{'Michael': 95, 'Tracy': 85}

set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key。要创建一个set,需要提供一个list作为输入集合:

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

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

基本类型转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> int('123')
123
>>> int(12.34)
12
>>> float('12.34')
12.34
>>> str(1.23)
'1.23'
>>> unicode(100)
u'100'
>>> bool(1)
True
>>> bool('')
False

数据类型检查可以用内置函数isinstance实现

is 与 == 的区别 比较两个字符串的区别

条件判断

1
2
3
4
5
6
7
8
if <条件判断1>:
<执行1>
elif <条件判断2>:
<执行2>
elif <条件判断3>:
<执行3>
else:
<执行4>

循环方式

1
2
3
4
5
6
7
8
9
10
names = ['Michael', 'Bob', 'Tracy']
for name in names:
print name

sum = 0
n = 99
while n > 0:
sum = sum + n
n = n - 2
print sum

函数

基本定义

1
2
3
4
5
def my_abs(x):
if x >= 0:
return x
else:
return -x

python函数返回的是单一值,但是这个单一值是一个tuple。函数可以同时返回多个值,但其实就是一个tuple

默认参数

1
2
3
4
5
6
def power(x, n=2):
s = 1
while n > 0:
n = n - 1
s = s * x
return s

在以上的代码中,当我们调用power(5)时,相当于调用power(5, 2)

默认参数必须放在实际的参数的后面,
默认参数必须指向不变对象(默认参数在函数被定义的时候就已经被创建好了)
可变参数 与 关键字参数(实际用起来总是不熟悉)
定义可变参数和定义list或tuple参数相比,仅仅在参数前面加了一个*号。在函数内部,参数numbers接收到的是一个tuple,因此,函数代码完全不变。但是,调用该函数时,可以传入任意个参数,包括0个参数。

1
2
3
4
5
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n * n
return sum

可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple

关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict

1
2
def person(name, age, **kw):
print 'name:', name, 'age:', age, 'other:', kw

函数person除了必选参数name和age外,还接受关键字参数kw。在调用该函数时,可以只传入必选参数,关键参数相当于是以key-value值的形式传入的参数,传入之后自动组成一个dict:

1
2
3
4
5
6
>>> person('Michael', 30)
name: Michael age: 30 other: {}
>>> person('Bob', 35, city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}

注意所以,对于任意函数,都可以通过类似func( args, *kw)的形式调用它,无论它的参数是如何定义的,在下面的装饰器语法中,就是这么使用的。

python 装饰器

  • 通过变量可以调用函数
  • 装饰器实际上返回的就是一个高阶函数,就是函数的函数
  • 装饰器通过@的语法生效
  • 1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # 定义一个可以打印日志的decorator
    def log(func):
    # 这里的wrapper可以接受任何的参数
    def wrapper(*args, **kw):
    print 'call %s():' % func.__name__
    return func(*args, **kw)
    return wrapper

    # 在now函数前 放置装饰器 相当于now=log(now)
    # now 函数被log装饰器所装饰 返回的now是一个新的now
    @log
    def now():
    print '2013-12-25'

python mysql

python-mysql 常见操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 导入MySQL驱动:
>>> import mysql.connector
# 注意把password设为你的root口令:
>>> conn = mysql.connector.connect(user='root', password='password', database='test', use_unicode=True)
>>> cursor = conn.cursor()
# 创建user表:
>>> cursor.execute('create table user (id varchar(20) primary key, name varchar(20))')
# 插入一行记录,注意MySQL的占位符是%s:
>>> cursor.execute('insert into user (id, name) values (%s, %s)', ['1', 'Michael'])
>>> cursor.rowcount
1
# 提交事务:
>>> conn.commit()
>>> cursor.close()
# 运行查询:
>>> cursor = conn.cursor()
>>> cursor.execute('select * from user where id = %s', ('1',))
>>> values = cursor.fetchall()
>>> values
[(u'1', u'Michael')]
# 关闭Cursor和Connection:
>>> cursor.close()
True
>>> conn.close()

ORM

相当于在程序中把db中的数据结构实现一下,常用到的工具就是sqlalchemy。

参考链接
http://docs.sqlalchemy.org/en/rel_1_0/core/type_basics.html

python的继承

Python元类(metaclass)

经典入门例子:http://blog.jobbole.com/21351/

之前还弄java的时候,整理过这个blog,听起来很奇怪,class类,类的类?实际上应该说成元类,即metaclass比较恰当。虽然具体使用方式不同,不过出发点应该都是类似的,就是对类本身的一个更高层次的抽象。

定义了一个类,这个类本身也可以被看成是另一层更高抽象的类(即元类)的实例或者说是定义出来的一个对象。

元类有什么所谓的magic things呢

  • 动态的创建类,因为meta class也是一种对象,所以可以像是其他对象一样,在函数中动态的创建。使用class关键字。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def create_class(name):
if name=='create_class_a':
class A(object):
pass
return A
if name=='create_class_b':
class B(object):
pass
return B
MyclassA=create_class('create_class_a')
print MyclassA
MyclassB=create_class('create_class_b')
print MyclassB
# MyclassB本身的类型是一个名为 type 的自建类型
print type(MyclassB)
# MyclassB的一个实例MyclassB()的类型是新创建的__main__.B类型
print type(MyclassB())
print type('MyclassC',(),{})
'''
output:
<class '__main__.A'>
<class '__main__.B'>
<type 'type'>
<class '__main__.B'>
<class '__main__.MyclassC'>
'''

使用type关键字也可以动态的创建类,通常上,type关键字用来描述一个对象的具体的类型。比如type(类名, 父类的元组(针对继承的情况,可以为空),包含属性的字典(名称和值))
到底什么是元类?元类就是创建类的类。这些类,相当于元类的对象。可以用类比的方式加深理解:str是用来创建字符串对象的类,而int是用来创建整数对象的类。type就是创建类对象的类。

Python中所有的东西,注意,我是指所有的东西——都是对象。这包括整数、字符串、函数以及类。它们全部都是对象,而且它们都是从一个类创建而来。这样倒是容易理解了。于是python中的所有对象都会有class这个属性。

那class的class会是什么呢,就是一个type类型,就像上面的例子中print type(MyclassB)所打印来的一样,type就是Python的内建元类。

元类的一些其他属性

  • metaclass属性 定义一个类的时候,如果其中存在metaclass这个属性,ython会在内存中通过metaclass创建一个名字为类名的类对象,如果不存在,继续向上找,从父类中寻找 metaclass属性 一直到最上层,如果没有找到,就用内建的type来创建类对象。

lamda 表达式

在项目中看到了一个很fancy的表达:

1
files = map(lambda f:os.path.normpath(os.path.join(f, 'etc', 'sstack', 'sstack.yml.dev')), sys.path)

首先看下map函数,这个有点类似于mapreduce中的map函数。
map(function, iterable, …)
map函数的功能就是将第一个参数所定义的函数施加到后面的一系列成员中去。有一点是要注意的iterable中的每个成员,会自动的被认为是function函数的形参,传入到函数中
在上面的操作中,sys.path返回的是当前python环境下的查找路径,具体来源可以参考这个。

上面的例子可以这样来解释,首先定义一个lambda表达式,表达式的形参为f,lambda函数的功能是把 /etc/sstack/sstack.yml.dev 的路径加入进来。

expression=lambda f:os.path.normpath(os.path.join(f, ‘etc’, ‘sstack’, ‘sstack.yml.dev’))·

之后使用map函数,将后面的每个item中的元素当成形参,传入到lamda函数中,执行对应的操作,之后返回经过处理之后的list:

files = map(expression, sys.path)

python 内置函数

getattr
这个函数多少有点java中反射的意思,Getattr用于返回一个对象属性,或者方法,根据属性的名称,返回对象的值,如果name是对象的属性的名称,则返回对应的属性的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class A:
def __init__(self):
self.a = 'a'
def method(self):
print "method print"
a = A()
print "output 1: "
# instance a contains the element 'a' print a
print getattr(a, 'a', 'default')
# instance a do not contain the element 'b' print default
print "output 2: "
print getattr(a, 'b', 'default')
# instance a contain the function 'method' return the address of function
print "output 3: "
print getattr(a, 'method', 'default')
# instance a contain the function 'method' return that function to value
# use value() to invoke the function and print it
print "output 4:"
value=getattr(a, 'method', 'default')
value()
""""
output:
output 1:
a
output 2:
default
output 3:
<bound method A.method of <__main__.A instance at 0x7f9bcf896a70>>
output 4:
method print
"""

reference

learn python step by step 的比较好的tutorial

https://intermediate-and-advanced-software-carpentry.readthedocs.io/en/latest/day2.html

推荐文章