这几天快速学习了下python,感觉python的一些东西还是和javascript相似,两者都是动态语言,只不过一个是后端的,一个是前端的,二者都有闭包的概念,都支持高阶函数,但总体感觉python是我所学过的最高级的语言,封装了不少高级方法,也有@xxx类似java注解的语法,花哨的地方不少,毕竟python的最初宗旨是简洁、优雅,用更少的代码完成更多的事。下面是一些笔记:
可以去官网(http://www.python.org)下载对应的版本的msi文件,安装好后加入到系统变量中,然后在电脑上创建一个python文件(hello.py),cmd打开命令行进入到hello.py所在的目录,执行python “hello.py”命令就可以执行python程序了。
下面写小的猜字程序:
#coding=utf-8
a = 23
#接收控制台输入的一个数
guess = input(u'plese input a num:')
print type(guess)
print type(a)
print guess == a
if guess == a:
print 'ok'
elif guess > a:
print 'max'
else:
print 'min'
1、空(None)
表示该值是一个空对象,空值是Python里一个特殊的值,用None表示。None不能理解为0,因为0是有意义的,而None是一个特殊的空值。python中None,’ ‘,0都可以表示False。
2、布尔类型(Boolean)
布尔值还可以用and、or和not运算。
3、整型(Int)
Python可以处理任意大小的整数,当然包括负整数。
4、浮点型(Float)
整数和浮点数在计算机内部存储的方式是不同的,整数运算永远是精确的(除法难道也是精确的?是的!),而浮点数运算则可能会有四舍五入的误差。
5、字符串(String)
Python字符串即可以用单引号也可以用双引号括起来,甚至还可以用三引号括起来。如果字符串里面有很多字符都需要转义,就需要加很多\,为了简化,Python还允许用r’ ‘表示”内部的字符串默认不转义。如果字符串内部有很多换行,用\n写在一行里不好阅读,为了简化,Python允许用”’…”’的格式表示多行内容。
6、列表(List) use a list as a stack
用符号[]表示列表,中间的元素可以是任何类型,用逗号分隔。list类似C语言中的数组,用于顺序存储结构。
内建函数:
7.元组(tuple)
元组是和列表相似的数据结构,但它一旦初始化就不能更改,速度比list快,同时tuple不提供动态内存管理的功能,需理解一下规则:
tuple可以用下标返回一个元素或子tuple
表示只含有一个元素的tuple的方法是:(d,)后面有个逗号,用来和单独的变量相区分。
t = 12345, 54321, 'hello!'
>>> t[0]
12345
>>>t, (1, 2, 3, 4, 5)
((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
>>>([1, 2, 3], [3, 2, 1])
([1, 2, 3], [3, 2, 1])
p1, p2 = ((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
print p1
(12345, 54321, 'hello!')
8、集合(Set)
集合是无序的,不重复的元素集,类似数学中的集合,可进行逻辑运算和算术运算,使用set(list)的形式构建一个set。
创建set的方式 s = set(["aa","bb"]) #set(['aa', 'bb']) a = set('abracadabra') #set(['a', 'r', 'b', 'c', 'd']) 不含重复元素 >>> {x for x in 'abracadabra' if x not in 'abc'} set(['r', 'd'])
9、字典(Dict)
字典是一种无序存储结构,包括关键字(key)和关键字对应的值(value)。字典的格式为:dictionary = {key:value}。关键字为不可变类型,如字符串、整数、只包含不可变对象的元组,列表等不可作为关键字。如果列表中存在关键字对,可以用dict()直接构造字典。
var = {"a": "crunchy", "b": "frog"}
>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
{'sape': 4139, 'jack': 4098, 'guido': 4127}
>>>del tel['sape']
{'jack': 4098, 'guido': 4127}
>>>'guido' in tel
True
>>> {x: x**2 for x in (2, 4, 6)}
{2: 4, 4: 16, 6: 36}
>>> dict(sape=4139, guido=4127, jack=4098)
{'sape': 4139, 'jack': 4098, 'guido': 4127}
函数式编程特点:
(1)把计算机视为函数而不是指令
(2)纯函数式编程:不需要变量,没有副作用,测试简单
(3)支持高阶函数,测试简单
python支持的函数式编程
(1)不是纯函数式编程,允许有变量
(2)支持高阶函数,函数也可作为变量传入
(3)支持闭包,有了闭包就能返回函数
map(),reduce(),filter(),闭包,匿名函数(lambda标识),decorator装饰器,偏函数(functools.partial())
这里面重点说一下decorator,Python的 decorator 本质上就是一个高阶函数,它接收一个函数作为参数,然后,返回一个新函数。使用 decorator 用Python提供的 @ 语法,这样可以避免手动编写 f = decorate(f) 这样的代码。
看例子,编写无参decorator
import time
def performance(f):
def fn(*args, **kw):
t = time.time()
print args
return f(*args)
return fn
@performance
def factorial(n):
return reduce(lambda x,y: x*y, range(1, n+1))
print factorial(10)
编写有参decorator
import time
def performance(unit):
def f1(f):
def f2(*args, **kw):
t1 = time.time()
print 'call %s() in %s%s' % (f.__name__, t1, unit)
return f(*args)
return f2
return f1
@performance('ms')
def factorial(n):
return reduce(lambda x,y: x*y, range(1, n+1))
print factorial(10)
注意:通过上面的例子我们可以看到,第一例子中函数的指向factorial传给了f,函数factorial的参数传给了*args。第二个例子中装饰器的参数传给了unit,函数的指向factorial传给了f,函数factorial的参数传给了*args。
class Person(object):
#实例属性每个实例各自拥有,互相独立,而类属性有且只有一份,当实例属性和类属性重名时,实例属性优先级高。
address = 'Earth'
count = 0
def __init__(self, name):
self.name = name
self._title = 'Mr'
#如果一个属性由双下划线开头(__),该属性就无法被外部访问。
self.__job = 'Student'
#定义实例方法,实例的方法就是在类中定义的函数,它的第一个参数永远是 self,指向调用该方法的实例本身,其他参数和一个普通函数是完全一样的:
def get_name(self):
return self.name
#定义类方法,类方法的第一个参数将传入类本身,通常将参数名命名为 cls,上面的 cls.count 实际上相当于 Person.count。
@classmethod
def how_many(cls):
return cls.count
p = Person('Bob')
print p.name
print Person.address
# self不需要显式传入
# => Bob
print p.get_name()
# => Earth
print Person.how_many()
# => 0
我们在 class 中定义的实例方法其实也是属性,它实际上是一个函数对象:
class Person(object):
def __init__(self, name, score):
self.name = name
self.score = score
def get_grade(self):
return 'A'
p1 = Person('Bob', 90)
print p1.get_grade
# => <bound method Person.get_grade of <__main__.Person object at 0x109e58510>>
print p1.get_grade()
# => A
也就是说,p1.get_grade 返回的是一个函数对象,但这个函数是一个绑定到实例的函数,p1.get_grade() 才是方法调用。
因为方法也是一个属性,所以,它也可以动态地添加到实例上,只是需要用 types.MethodType() 把一个函数变为一个方法:
import types
def fn_get_grade(self):
if self.score >= 80:
return 'A'
if self.score >= 60:
return 'B'
return 'C'
class Person(object):
def __init__(self, name, score):
self.name = name
self.score = score
p1 = Person('Bob', 90)
p1.get_grade = types.MethodType(fn_get_grade, p1, Person)
print p1.get_grade()
# => A
p2 = Person('Alice', 65)
print p2.get_grade()
# ERROR: AttributeError: 'Person' object has no attribute 'get_grade'
# 因为p2实例并没有绑定get_grade
给一个实例动态添加方法并不常见,直接在class中定义要更直观。
如果已经定义了Person类,需要定义新的Student和Teacher类时,可以直接从Person类继承:
class Person(object):
def __init__(self, name, gender):
self.name = name
self.gender = gender
def whoAmI(self):
return 'I am a Person, my name is %s' % self.name
class Student(Person):
def __init__(self, name, gender, score):
super(Student, self).__init__(name, gender)
self.score = score
def whoAmI(self):
return 'I am a Student, my name is %s' % self.name
def who_am_i(x):
print x.whoAmI()
p = Person('Tim', 'Male')
s = Student('Bob', 'Male', 88)
who_am_i(p)
who_am_i(s)
定义Student类时,只需要把额外的属性加上,如上面的score。一定要用 super(Student, self).init(name, gender) 去初始化父类,否则,继承自 Person 的 Student 将没有 name 和 gender。函数super(Student, self)将返回当前类继承的父类,即 Person ,然后调用init()方法。注意,self参数已在super()中传入,在init()中将隐式传递,不需要写出(也不能写)。
上面who_am_i方法的调用执行行为称为多态。也就是说,方法调用将作用在 x 的实际类型上。s 是Student类型,它实际上拥有自己的 whoAmI()方法以及从 Person继承的 whoAmI方法,但调用 s.whoAmI()总是先查找它自身的定义,如果没有定义,则顺着继承链向上查找,直到在某个父类中找到为止。
由于Python是动态语言,所以,传递给函数 who_am_i(x)的参数 x 不一定是 Person 或 Person 的子类型。任何数据类型的实例都可以,只要它有一个whoAmI()的方法即可。
另一种继承方式,通过apply()函数实现继承:
class Rectangle:
def __init__(self, color="white", width=10, height=10):
print "create a", color, self, "sized", width, "x", height
#*args是非关键字参数,用于元组,**kw是关键字参数,用于字典
class RoundedRectangle(Rectangle):
def __init__(self, **kw):
apply(Rectangle.__init__, (self,), kw)
rect = Rectangle(color="green", height=100, width=100)
rect = RoundedRectangle(color="blue", height=20)
isinstance() 判断变量的类型
>>> isinstance(p, Person)
True # p是Person类型
type() 函数获取变量的类型
>>> type(123)
<type 'int'>
>>> s = Student('Bob', 'Male', 88)
>>> type(s)
<class '__main__.Student'>
dir() 返回所有实例属性
dir(123) # 整数也有很多属性...
['__abs__', '__add__', '__and__', '__class__', '__cmp__', ...]
>>> dir(s)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__',
'__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'gender', 'name', 'score', 'whoAmI']
注意到方法whoAmI
也是 s 的一个属性。
getattr()/setattr( ) 获取/设置对象的属性
>>> getattr(s, 'name') # 获取name属性
'Bob'
>>> setattr(s, 'name', 'Adam') # 设置新的name属性
>>> getattr(s, 'age', 20) # 获取age属性,如果属性不存在,就返回默认值20