python学习笔记

    这几天快速学习了下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语言中的数组,用于顺序存储结构。
内建函数:

  • append(x)追加到链尾
  • extend(L)追加一个列表,等价于+=
  • insert(i,x)在位置i插入x,其余元素向后推,如果i大于列表长度,就在最后添加,如果i小于0,就在最开始添加
  • remove(x)删除第一个值为x的元素,如果不存在会抛出异常
  • reverse()反转序列
  • pop([i])返回并删除位置为i的元素,i默认为最后一个元素
  • index(x)返回x在列表中第一次出现的位置,不存在则抛出异常
  • count(x)返回x出现的次数
  • sort()排序
  • len(List)返回List的长度
  • del list[i]删除列表list中指定的第i+1个变量
    切片指的是抽取序列的一部分,其形式为:list[start:end:step]。python没有类似java对字符串的操作,python中可以用切片对字符串进行操作,例如截取字符串的一部分。
    生成列表
    print [x * x for x in range(1, 11)]
    [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
    列表生成式的 for 循环后面还可以加上 if 判断。例如:
    print [x * x for x in range(1, 11) if x % 2 == 0]
    [4, 16, 36, 64, 100]

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。

面向对象编程

  • 在Python中,类通过 class 关键字定义。
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

你可能感兴趣的:(python,入门)