人生苦短
我用Python

Python 语法

mediastack阅读(199)

Python因为它的易学性,被大众所青睐。也是被公认较为容易上手的编程语言之一,是最为受初学者喜欢的语言。学习Python 开发项目前,我们先来了解下Python的前世今生,以及简单的语言使用语法,更多的语法知识可能需要我们花费更多的时间来敲代码发现。请记住:”Life is short,you need Python“。

起源

Python由荷兰数学和计算机科学研究学会的Guido van Rossum 于1990 年代初设计,作为一门叫做ABC语言的替代品。 Python提供了高效的高级数据结构,还能简单有效地面向对象编程。1989年圣诞节期间,在阿姆斯特丹,Guido为了打发圣诞节的无趣,决心开发一个新的脚本解释程序,作为ABC语言的一种继承。之所以选中Python(大蟒蛇的意思)作为该编程语言的名字,是取自英国20世纪70年代首播的电视喜剧《蒙提·派森的飞行马戏团》(Monty Python’s Flying Circus)。

安装

Python 目前分为两个大版本 Python 2.X和Python 3.X,推荐使用当前最新的稳定版 Python 3.8.7

变量

python中变量赋值不需要类型声明,每个变量在内存中创建,都包括变量的标识,名称和数据这些信息。变量使用前必须赋值,变量赋值后才可被创建。

x = 12
print(x)

python 定义了五个标准数据类型:

Number

数字类型,内置支持类型有:int(有符号的整型)、long(长整型)、float(浮点型)、complex(复数)

var1 = 1
var2 = 10
var 3 = float(10)

String

字符串类型,字符串是 Python 中最常用的数据类型。我们可以使用引号(‘或”)来创建字符串。

var1 = 'Hello World!'
var2 = "Python Runoob"

print "var1[0]: ", var1[0]
print "var2[1:5]: ", var2[1:5]

列表(List)

序列是Python中最基本的数据结构。Python 中包含6种内建的序列,如下:

  • List:列表
  • Tupple:元组
  • String:字符串
  • Unicode:Unicode字符串
  • Buffer
  • xrange

列表的特点在于可以修改。有所有序列结构的通用操作,操作类型包括:

  • 索引(indexing)
  • 切片(slicing)
  • 加(adding)
  • 乘(multiplying)
  • contain (包含检测)
  • length (长度)
  • 迭代
#!/usr/bin/python
list = []   
list1 = ['physics', 'chemistry', 1997, 2000]
list2 = [1, 2, 3, 4, 5, 6, 7 ]

# 索引
print "list1[0]: ", list1[0]
print "list2[1:5]: ", list2[1:5]

# list1[0]:  physics
# list2[1:5]:  [2, 3, 4, 5]

# 新增
list.append('Google')   ## 使用 append() 添加元素
list.append('Runoob')

print(list)

# ['Google','Runoob']

# 删除
del list2[2]

# [1,2,4,5,6,7]

# 切片
a = list1[2:]
print(a)
print(list1[-2])
# ['chemistry', 1997, 2000]
# 1997

元组(Tupple)

元组和列表一样,也是一种序列,见上。与列表不同的是元组不可修改。元组的创建如下:

a = (1,2,3)
b = (1,) # 元组中只包含一个元素时,需要在元素后添加逗号,

元组中的元素值是不允许修改的,但我们可以对元组进行连接组合,如下实例:

#!/usr/bin/python
# -*- coding: UTF-8 -*-

tup1 = (12, 34.56)
tup2 = ('abc', 'xyz')

# 以下修改元组元素操作是非法的。
# tup1[0] = 100

# 创建一个新的元组
tup3 = tup1 + tup2
print tup3


# (12, 34.56, 'abc', 'xyz')

字典(Dictionary)

字典是Python 中唯一内建的映射类型。字典中的值并没有特殊的顺序,但是都存储在一个特定的键(key)中。key可以是任一不可变类型。

字典的每个键值 key=>value 对用冒号 : 分割,每个键值对之间用逗号 , 分割,整个字典包括在花括号 {} 中 ,格式如下所示:

d = {key1 : value1, key2 : value2 }

键一般是唯一的,如果重复最后的一个键值对会替换前面的,值不需要唯一。

#!/usr/bin/python

dict = {'Name': 'Zara', 'Age': 7, 'Class': 'First'}

print "dict['Name']: ", dict['Name']
print "dict['Age']: ", dict['Age']


# dict['Name']:  Zara
# dict['Age']:  7

字典的基本行为在很多方便与序列相似:

  • 求长度
  • 索引:d[k]
  • 删除:del
  • 检测是否包含

字典特性:

  • 字典的key是唯一的,后赋值的值会覆盖前面的
  • 键必须不可变(列表不可作为键)

流程控制

Python 中的流程和其他编程语言一样,主要包括条件语句、循环语句。

  • if else 条件语句
#!/usr/bin/python
# -*- coding: UTF-8 -*-

# 例1:if 基本用法

flag = False
name = 'luren'
if name == 'python':         # 判断变量是否为 python 
    flag = True              # 条件成立时设置标志为真
    print 'welcome boss'     # 并输出欢迎信息
else:
    print name               # 条件不成立时输出变量名称


##    luren            # 输出结果

需要注意的是,python是格式严格的语言,通过缩排格式来控制运行语句。

  • while 循环
#!/usr/bin/python

count = 0
while (count < 9):
   print 'The count is:', count
   count = count + 1

print "Good bye!"
  • for循环
#!/usr/bin/python
 
count = 0
while (count < 9):
   print 'The count is:', count
   count = count + 1
 
print "Good bye!"

其他特性

pass语句

Python pass 是空语句,是为了保持程序结构的完整性。pass 不做任何事情,一般用做占位语句。

#!/usr/bin/python
# -*- coding: UTF-8 -*- 
 
# 输出 Python 的每个字母
for letter in 'Python':
   if letter == 'h':
      pass
      print '这是 pass 块'
   print '当前字母 :', letter
 
print "Good bye!"

break 语句

break语句用来终止循环语句,即循环条件没有False条件或者序列还没被完全递归完,也会停止执行循环语句。

break语句用在while和for循环中。如果您使用嵌套循环,break语句将停止执行最深层的循环,并开始执行下一行代码。

#!/usr/bin/python
# -*- coding: UTF-8 -*-
 
for letter in 'Python':     # 第一个实例
   if letter == 'h':
      break
   print '当前字母 :', letter
  
var = 10                    # 第二个实例
while var > 0:              
   print '当前变量值 :', var
   var = var -1
   if var == 5:   # 当变量 var 等于 5 时退出循环
      break
 
print "Good bye!"

continue 语句

continue 语句跳出本次循环,而break跳出整个循环。

#!/usr/bin/python
# -*- coding: UTF-8 -*-
 
for letter in 'Python':     # 第一个实例
   if letter == 'h':
      continue
   print '当前字母 :', letter
 
var = 10                    # 第二个实例
while var > 0:              
   var = var -1
   if var == 5:
      continue
   print '当前变量值 :', var
print "Good bye!"

接下来,会介绍些Python的高阶使用。

python变量

mediastack阅读(228)

变量存储在内存中的值。这就意味着在创建变量时会在内存中开辟一个空间。基于变量的数据类型,解释器会分配指定内存,并决定什么数据可以被存储在内存中。因此,变量可以指定不同的数据类型,这些变量可以存储整数,小数或字符。

赋值

python中变量赋值不需要类型声明
每个变量在内存中创建,都包括变量的标识,名称和数据这些信息。
变量使用前必须赋值,变量赋值后才可被创建
变量赋值格式: a = 12
python允许多个变量同时赋值,格式为: a = b = c =100或者a,b,c,d=1,34,”test”,99
标准数据类型

python 定义了五个标准数据类型:

  • Numbers(数字)
  • String(字符串)
  • List(列表)
  • Tupple(元组)
  • Dictionary(字典)

数字数据类型为不可改变数据类型,当改变数字数据类型对象时会分配一个新的对象创建,可以直接通过赋值方式创建一个数字数据类型对象,每赋值一个数字类型就会创建一个新的对象。格式为:var1=101
删除 通过del语句删除 del var1,var2,…,varN
支持类型如下:

  • int(有符号的整型)
  • long(长整型)
    也可代表八进制和十六进制]:长整型也可以使用小写”L”,但是还是建议您使用大写”L”, 避免与数字”1″混淆。Python使用”L”来显示长整型。
  • float(浮点型)
  • complex(复数)
  • String(字符串)
    字符串由数字、字母、下划线组成的一串字符。

取值方式 python中有两种方式对当前的字符串进行取值:

  • 从左到右取值默认从0开始,最大范围为字符长度减1
  • 从右到左取值默认从-1开始。

截取字串格式: str[begin:over]下标可以为0表示从头开始或到尾部截止。注意begin指定的字符需要在over左侧,否则无法取到。 3)切片操作:str[begin:over:step],对str截取后的字符串以step步长进行切片分割。
List(列表)是python 中使用最频繁的数据结构,可以完成大多数集合类结构的数据结构实现。支持字符、数字、字符串以及列表。通过[]进行标识,列表的截取方式和String的字串截取方式相同.[begin:over] 1)加号(+)是列表连接运算符,星号(*)是重复操作。如下案例:

List

list =['testa','bbb',123433,40.6]
a=['test','a',999]

print list
list[3]=3
print list[2:3]
print list+a
print list * 2

Tupple(元组)

元组类似与List,但是元组不可二次赋值,使用()标志,同样通过逗号分割,tupple的获取和List方法相同。如下为用法示例:

#tupple
tuple = ('tupple top',123,23.45,'tupple end')
t2 = (123.4,45,'tt',109)
print tuple
print t2
print  tuple[:4]

#tuple[3]=3  //该操作无效,元组不允许修改更新
print tuple * 2
print tuple+t2

Dictionary(字典)

类似与List,List有序、Dictionary无序(类似与Java中的map,通过key-value方式存储),格式通过{key:value,….}赋值。和json数据格式很相像.如下,给出一个简单的操作示例:

  #dictionary
dict = {'key1':'value1','key2':23,2:"gg"}

print dict
#print dict[0] //这种操作是不合法的
print dict[2]
print dict.keys()
print dict.values()
dict2=dict.copy()
print dict2

数据类型转化

通过函数实现数据类型的转换。对应函数如下:

int(x [,base]) 将x转换为一个整数 long(x [,base] ) 将x转换为一个长整数 float(x) 将x转换到一个浮点数 complex(real [,imag]) 创建一个复数 str(x) 将对象 x 转换为字符串 repr(x) 将对象 x 转换为表达式字符串 eval(str) 用来计算在字符串中的有效Python表达式,并返回一个对象 tuple(s) 将序列 s 转换为一个元组 list(s) 将序列 s 转换为一个列表 set(s) 转换为可变集合 dict(d) 创建一个字典。d 必须是一个序列 (key,value)元组。 frozenset(s) 转换为不可变集合 chr(x) 将一个整数转换为一个字符 unichr(x) 将一个整数转换为Unicode字符 ord(x) 将一个字符转换为它的整数值 hex(x) 将一个整数转换为一个十六进制字符串 oct(x) 将一个整数转换为一个八进制字符串

参数数据类型判断获取

1.通过type(param)返回参数类型,显示如下格式:

<type 'dict'>

2.通过isinstance 来判断,如下:

print isinstance(2,int)
##显示结果
True

注意

  • 尽量不要使用内部函数名作为变量的名称,否则在使用该内部函数的时候回报:TypeError: ‘list’ object is not callable错误;
  • 数据类型分为数字型和非数字型。数字型包括整型,长整型,浮点型,复数型;非数字型包括字符串,列表,元组和字典 ;
  • 非数字型的相同点:都可以进行切片、连接(+)、重复(*)、取值([])等相关操作;
  • 非数字型不同点:列表可以直接赋值并对其进行更新修改,元组赋值后不可更改,字典通过(key,vlaue)存储,通过key取值进行更新修改。

Python Exception处理

mediastack阅读(204)

Python中的错误处理分为两类:语法错误和异常处理。语法错误一般是指由于python语句、表达式、函数等存在书写格式活语法规则上的错误抛出的异常,如python常见的缩进控制,若同层次的执行语句存在缩进不同,会报语法错误(SyntaxError),一般在ide中会有明显的提示,其属于编译阶段的错误,一般是导致解析错误抛出错误;异常处理一般是指python语法格式正确,但在运行过程出现错误,错误类型交由python中的内建异常进行说明,回朔处理,这种类型的处理一般都是出现在运行阶段,是需要我们处理的。如下给出两种错误异常的简单案例.

#语法异常,导致的解析错误

str="just show syntax type error."
 print str,"\n"

 File "exception.py", line 21
   print str,"\n"
   ^
IndentationError: unexpected indent




#内置异常处理
s=None
a=12
print a*s

Traceback (most recent call last):
  File "exception.py", line 24, in exceptionDemo
    print a*s
TypeError: unsupported operand type(s) for *: 'int' and 'NoneType'

如上,IndentationError属于SyntaxError的派生子类,其和TypeError均是派生自Exception而来的,理论上来是Exceptioon可以说是python中所有异常的父类,但只是理论,除了Exception派生的异常内置类外还存在按键异常退出,系统异常退出等异常不属于Exception派生的,根据层次结果,可以确认的是,python中所有异常的父类是BaseException(该类是从python2.5新增的),如下给出内置异常处理类的基本层次结构。

BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StandardError
      |    +-- BufferError
      |    +-- ArithmeticError
      |    |    +-- FloatingPointError
      |    |    +-- OverflowError
      |    |    +-- ZeroDivisionError
      |    +-- AssertionError
      |    +-- AttributeError
      |    +-- EnvironmentError
      |    |    +-- IOError
      |    |    +-- OSError
      |    |         +-- WindowsError (Windows)
      |    |         +-- VMSError (VMS)
      |    +-- EOFError
      |    +-- ImportError
      |    +-- LookupError
      |    |    +-- IndexError
      |    |    +-- KeyError
      |    +-- MemoryError
      |    +-- NameError
      |    |    +-- UnboundLocalError
      |    +-- ReferenceError
      |    +-- RuntimeError
      |    |    +-- NotImplementedError
      |    +-- SyntaxError
      |    |    +-- IndentationError
      |    |         +-- TabError
      |    +-- SystemError
      |    +-- TypeError
      |    +-- ValueError
      |         +-- UnicodeError
      |              +-- UnicodeDecodeError
      |              +-- UnicodeEncodeError
      |              +-- UnicodeTranslateError
      +-- Warning
           +-- DeprecationWarning
           +-- PendingDeprecationWarning
           +-- RuntimeWarning
           +-- SyntaxWarning
           +-- UserWarning
           +-- FutureWarning
       +-- ImportWarning
       +-- UnicodeWarning
       +-- BytesWarning

而我们常见的自定义异常类一般均是继承自Exception。如下部分也是主要介绍非系统错误,退出导致的异常的处理的相关用法。主要通过如下几个方面介绍异常处理:

  • 异常捕获
  • 异常抛出
  • 异常自定义
  • 扩展清理操作预定义

异常捕获

python中如果应为某些操作(如上的NoneType)导致异常,若是一直未能被捕获,该异常将一直被传递,直至最后终止程序,抛出回朔。我们可以通过在程序中预测异常的发生添加异常的捕获处理,显示友好的用户交互提醒来防止程序的异常结束。python中的异常处理语句以及简单的使用如下:

try:
    '捕获异常的代码执行片段'
    s = None
    a = 12
    print a * s
except IOError:         #except为异常发生触发运行片段关键词,可以指定内置异常类类型,采用匿名类型,不获取异常信息
    print "catch IOError."
except TypeError as error: #捕获异常定义异常变量,新的API采用'as'来指定变量名称.
    print "catch TypeError.",error
except (UnboundLocalError,BufferError):    #捕获异常定义捕获的异常类型可以使用元组的形式添加多个捕获的异常类型.
    pass          #pass无意义占位关键字
except Exception,error:    #捕获异常Exception,将捕获所有的继承自Exception类型的异常,该种定义异常变量的方法属于老的api,新的api向下兼容.
    print "catch Exception and use \',\' define param.",error
except:        #捕获所有的异常类型包括系统异常退出等.
    pass
else:        #else为未发生异常执行的代码块,必须在except之后
    print "no catch any Exception."
finally:    #finally不管有没有出现异常均会执行,可以和try单独使用,一般用于资源的关闭操作.

针对如上的示例,总结如下异常捕获的关键点

  • 异常捕获使用格式: try …except….
  try:
      statement...
  except:
      statement...
  • 异常捕获可以指定异常捕获类型,并可以指定异常变量,指定变量有两种方式,一种通过’,’隔开,一种通过关键字’as’指定,格式如下:
  #','隔开

  try:
      statement...
  except Exception , error:
      pass


  #as指定
  try:
      statement...
  except Exception as error:
      pass
  • 捕获多种类型的异常可以直接通过元组的方式添加多个异常类型,也可以通过多个except指定,如下:
#元组表示
try:
    statement...
except (TypeError,IOError):
    statement...


#多个except
try:
    statement...
except TypeError:
    statement...
except IOError:
    statement...
  • 使用else代码块处理异常未发生的情况,如下:
try:
    statement...
except Exception , error:
    pass
else:
    statement... #没有发生异常
  • 使用finally处理无论是否发生异常捕获都执行的代码,可以直接通过和try单独使用,也可以和except联合使用(此种情况放在except,else后面)
#和except联合使用
try:
    statement...
except Exception , error:
    pass
finally:
    statement...

#和try单独使用
try:
    statement...
finally:
    statement...

异常抛出

异常抛出可以让我们定义主动抛出异常的逻辑,以提醒使用者需要进行某些必要的异常判断或者处理,python中的异常抛出使用关键字raise实现,raise的使用方式或者说是基本的使用场景可以分为三类:

  • 匿名抛出

常用抛出,可以直接指定抛出异常类即可,如下:

raise IOError

Traceback (most recent call last):
  File "exception.py", line 84, in <module>
    raise IOError
IOError
  • 实例抛出

实例抛出可以添加异常抛出显示的提示文本内容,以便帮助定位异常问题,如下:

error=IOError("the file is not exists.")
raise error

Traceback (most recent call last):
  File "exception.py", line 85, in <module>
    raise error
IOError: the file is not exists.
  • 捕获抛出

这种抛出不常见,但很使用,一般异常抛出关键字raise是需要跟一个类或者变量,但这种抛出不要添加任何其他信息,属于一种异常的传递,如下:

a = 12
s = None
try:
    print a*s
except Exception as error:
    if a < 10:
        pass
    else:
        raise   #抛出异常.除了该种情况,raise后面必须要有异常信息(类或者实例)

异常自定义

python中自定义异常一般是继承Exception或者Exception的子类,可以默认继承不做处理也可以通过对其进行定制,如下给出两个示例,一个为简单的集成,一个为重写方法,如下:

#直接继承不做处理
class DefException(Exception):
    pass


raise DefException("Def Exception")


Traceback (most recent call last):
  File "exception.py", line 101, in <module>
    raise DefException("Def Exception")
__main__.DefException: Def Exception


#重写__init__
class CustomerException(Exception):
    KEY_CODE="code"
    KEY_MESSAGE="message"
    def __init__(self,**args):
        self.code=args[CustomerException.KEY_CODE]
        self.message=args[CustomerException.KEY_MESSAGE]

    def __str__(self):
        print repr(" throw code:%s,message:%s" % (self.code,self.message))

raise CustomerException(code=21,message="this is customer Exception")



#result
Traceback (most recent call last):
' throw code:21,message:this is customer Exception'
  File "/home/hfcai/Projects/PythonProjects/pythonNotes/exercises/basics/exception.py", line 115, in <module>
    raise CustomerException(code=21,message="this is customer Exception")
__main__.CustomerException

扩展清理操作预定义

这是python对于文件操作提供的一个自动在操作完成后关闭的操作,使用关键字with实现,如下所示:

with open(name="./struct.py",mode="rb+")  as file:   #这是文件的打开操作.
     print file.read()               #文件的读取操作

如上,当执行完with下的代码块,file会自动关闭,不论是否发生异常.

参考

Python控制流

mediastack阅读(182)

控制流即判断语句,python中的判断语句包括有:if语句,while语句,for语句.python中并没有类似的swith语句

if语句

python中if语句的写法和java,C有点不一样的是使用elif代替else if 而且必须每个代码块内部必须要包含代码,如此就需要引入一个比较重要的语句:pass语句

pass语句是一个比较奇葩的语句,他不做任何事情,但是就是占着这个位置,这样就保证了python代码块格式的统一和完整了,如下示例:

if param=="Open":
       print "yes"
   elif param =="close":
       print "No"
   else:
       pass

while语句

while语句用于循环执行,基本和C、Java没什么区别。如下:

a=7
while a>=0:
    if a==1:
        continue
    elif a==0:
        break
    else:
        a-=1
    print "a value:",a

for语句

python for循环语句用于遍历操作,python中的for循环不仅可以对集合等遍历,也可以对字符串进行便利.格式如下:

b="testbbb"
   for a in b:
       print a

   test=["A","B","C","D"]
   for a in range(10):
       print test[a]

range()函数为python内置函数,用于生成等差数列,默认等差值为1,也可手动设置数值大小.

Python 函数和类

mediastack阅读(207)

python作为一个面向对象的语言,也有类似java等面向对象语言相同的数据结构(class)的定义,和代码块数据结构定义“函数”。为了极大可能的简化代码调用逻辑和书写规则,python中对于函数和类的定义与使用也是及其简单的。函数也可以称作方法的定义使用有两种:一种是通过关键字def定义函数格式,另一种是通过lambda构建一个匿名函数。类的定义主要是通过关键字class定义完成,具体类相关的内容会在下面总结.

Python中的函数

python中函数的使用可以分为两种,若仔细研究会发现还有一种类似类型(列表解析),但其更像一个表达式。如下一一总结:

  • lambda

python中可以通过lambda表达式来构建一个简单的单行匿名函数。其结构简单,使用轻便,但功能也及其有限。其格式如下:

multi=lambda x,y:x*y #lambda关键字定义,以':'分割,左边为参数列表,右边为返回结果的表达式
print multi(2,3)

如上为一个简单的lambda形式创建的函数模式,可以通过其计算两个数的积,对于这类较为简单的计算可以直接使用lambda创建一个建议的函数实现。

def定义的函数可以完成较为复杂的工作,其定义格式如下

#定义格式
def [function_name]([parameter list]):
    'the function introduction' #注释文档,作为文档说明使用
    [statement] #缩进排版,确定代码块


#示例
def function(var1,var2="test"):
    'only print parameter.'
    print var1,var2

help(function)
function("need","help")
function(var2="var2",var1="var1")
function("var1")


#result

Help on function function in module __main__:

function(var1, var2='test')
    only print parameter.

need help
var1 var2
var1 test

如上,给出了函数的定义格式和示例代码,python中的函数调用参数不需要指定类型,函数以”:”开始进行逻辑实现,函数头部和函数体之间需要使用缩排来分割。上面的代码给出了三种调用方式,正好反映了函数的三个调用特性(个人总结,说词可能有点不太准确,但意思达到):

  1. 调用参数顺序调用 一般的调用方式,也是较为常见的调用
  2. 指定参数名调用 python中调用函数可以通过指定参数的函数指定参数值来调用函数,如:
  function(var2="var2",var1="var1") #这样可以更加容易的了解参数对应的含义,前提得是个好名字.
  1. 选择调用s python方法中可以指定参数的默认值,若不需要修改参数值的话可以省略对该参数的调用,使用见上示例最后一个调用。

python中的类

python中的类和一般的面向对象语言没什么太大的区别,具有一般类的基本特性:封装抽象多态继承 特性。和其他语言不同的是python中的类有两种类型的类:新式类和旧式类,在python2.x中默认创建的类为旧式类,python3.x默认茶ungjian的是新式类。

类的定义

类的定义和函数类似,需要使用一个关键字“class”来定义,定义语法结构如下:

class className:
   [statement]

如此就是一个类的定义,一个类中存在很多元素构成,如下为一个类的使用的示例,参考示例来了解类的成员类型:

class TestClass:   #类的定义
    DESCRIPTION = "class introduction"  # 类变量,可直接通过类名调用
    __test = "test"  # 属于私有,不可在类外部直接调用以“__”开头
    _single = "single"  # 属于私有,不可使用from module import *导入使用

    def __init__(self,name):
        '测试类'        #注释文档
        self.name=name #通过self可以创建类的实例变量
        print TestClass.__test
        print TestClass._single


    def getName(self): #类的成员方法
        return self.name


    def __getName(self): #类的私有方法
        return TestClass._single    

    @staticmethod
    def getsingele():   #类的静态方法
        return TestClass.__test



print TestClass.DESCRIPTION
print TestClass.getsingele()
test=TestClass("hfcai")
print test.name
print test.getName()
print TestClass.getName(test)



#result

class introduction
test
test
single
hfcai
hfcai
hfcai
  • 构造方法

实例化类(类的创建)需要通过调用其构造函数来实例化,python中的实例化会自动调用类的构造方法init(),可以通过指定init方法参数来实例化对象,同时需要注意的是一个类中只能有一个init函数。

  • 类的实例变量 python 中的类的实例化对象的创建需要通过self来创建,实例化对象完成后也可以通过类的变量进行调用
  • 类的实例方法 类的实例方法和普通的python函数类似,唯一不同的是类的成员犯法的参数列表首个参数必须是self,该方法的调用可以通过类的实例直接调用,不需要对首个self进行传递,默认为实例本身,也可以通过类名直接调用,但需要给self传值,参数为当前类的实例。
  • 类的静态方法 类的静态方法需要通过@@staticmethod定义,从次下一行开始定义方法(和函数相同).调用可以直接通过类名调用。
  • 类的变量 类似于java中的静态变量,需要通过类名调用

需要注意的是类的私有熟悉,类中所有以” _ ” 开头的方法、参数,均不可在类的外部直接调用,所有以“ ” 开头的方法、参数均不可使用
“from module import * ” 来直接调用.

新式类和旧式类

新式类是从python 2.2开始引入,python2.x默认创建的都是旧式类,python3.x默认创建的都是新式类。新式类是继承自object,其功能是为了保证class和type的统一,使用实例的class属性和type(实例)会返回相同的结果,但旧式类不一定。新式类对于多重继承的搜索算法进行了修改。对于python2.x来说想要定义形式类可以通过如下两种方法:

  • 继承object

直接显式继承自object可创建新式类

  • ** metaclass = type ** 直接在类的声明前添加“metaclass = type”

如下示例:

#!/usr/bin/env python
# -*-encoding:utf-8 -*-

class A:       #旧式类
    def __init__(self):
        print "classic type."

class B(object):  #新式类
    def __init__(self):
        print "new style type. one"

__metaclass__ =type
class C:               #新式类
    def __init__(self):
        print "new style type. two"

a=A()
b=B()
c=C()
print "class A __class__:%s,type:%s \n"% (a.__class__,type(a))
print "class B __class__:%s,type:%s \n"% (b.__class__,type(b))
print "class C __class__:%s,type:%s \n"% (c.__class__,type(c))



#result
classic type.
new style type. one
new style type. two
class A __class__:__main__.A,type:<type 'instance'>
class B __class__:<class '__main__.B'>,type:<class '__main__.B'>
class C __class__:<class '__main__.C'>,type:<class '__main__.C'>

Python 魔法方法与属性

mediastack阅读(231)

python的魔法方法很奇特,有些地方也称他为特殊方法。其结构是由两个下划线(“_”开始中间名称最后以两个下划线(“_”)结束的特殊指定方法,这有点类似java中的接口和abstract,是python中定义的一种规则,一种玩法。这也是python与java对于方法重写的一个较大的不同的地方.Java中我们可能会为了实现某种或某类相似的动作行为(action),从而使用接口式编程,抽象方法来抽象实现过程从而实现其多态性
,而且子类(非抽象类)继承了抽象父亲或者实现了接口后,必须要是实现所继承父类或接口的抽象方法,可以明显发现Java中的多态是基于对象的(父类或接口),而python中的“接口实现方式”方式与其有很大的不同,python中的多态是基于动作和特性的实现的,即操作动作决定方法实现,只要对象实现了对应的魔法方法就可使用python中的某些特殊操作方式对该对象进行操作,而一般这种”特殊操作“的本质是将其内到python的内建函数的操作中。而内建函数操作的本质是根据区分操作对象的数据结构进行调用的,所以木法方式的作用是通过重写类的魔法方法从而实现将类转化为某类数据结构类型的作用(常见的结构类型有:序列、映射、集合和特殊的结构类型迭代器等)。所以魔法方法的大部分内容是围绕如下几个部分的(类,方法,重写,内建函数,数据结构)来展开的。可以分为如下几个部分进行分段了解:

内建函数

python内建函数是一个比较重要的功能,内建函数在某些特定的情况下可以代码的复杂性和增强代码的可读性,内建函数是存在于python的’** builtins **’模块的一些函数,相对于其他模块,存在于’ **buildins‘模块的函数与变量并不需要我们通过import导入,属于python内置模块.内建函数的介绍链接Python 内建函数,也可以借助python本省来了解.可以通过dir(builtins)来获取 builtins ** 中的对象和函数:

print "all params of Built-in :\n"
print dir(__builtins__),"\n"#显示__builtins__模块的所有信息

#print "__builtins__ hep info:\n"
#help(__builtins__) #显示内置函数的基本用法介绍

#classmethod  help doc
#help(classmethod)   
#staticmethod help doc
#help(staticmethod)
#iter help doc
#help(iter)
help(next)
all params of Built-in :

['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'BufferError', 'BytesWarning', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False', 'FloatingPointError', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarning', 'IndentationError', 'IndexError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 'None', 'NotImplemented', 'NotImplementedError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'ReferenceError', 'RuntimeError', 'RuntimeWarning', 'StandardError', 'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 'ValueError', 'Warning', 'ZeroDivisionError', '__IPYTHON__', '__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs', 'all', 'any', 'apply', 'basestring', 'bin', 'bool', 'buffer', 'bytearray', 'bytes', 'callable', 'chr', 'classmethod', 'cmp', 'coerce', 'compile', 'complex', 'copyright', 'credits', 'delattr', 'dict', 'dir', 'display', 'divmod', 'dreload', 'enumerate', 'eval', 'execfile', 'file', 'filter', 'float', 'format', 'frozenset', 'get_ipython', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'intern', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'long', 'map', 'max', 'memoryview', 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property', 'range', 'raw_input', 'reduce', 'reload', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'unichr', 'unicode', 'vars', 'xrange', 'zip'] 

Help on built-in function next in module __builtin__:

next(...)
    next(iterator[, default])

    Return the next item from the iterator. If default is given and the iterator
    is exhausted, it is returned instead of raising StopIteration.

内置函数中有dir可以获取python中的模块信息,还有类似abs之类的数学计算的函数。如下,仅仅介绍几个和魔法方法y以及和类相关的内置函数:

  • classmethod(function) 将方法function封装成类的方法,被定义成装饰器(decorator),具体实现可以通过两种方式,一种是直接通过装饰器定义,被装饰器修饰的方法会默认被传入该方法,也可以直接通过方法调用实现,与其类似的有staticmethod函数示例如下:
  class A:

      #装饰器
      @classmethod
      def methodA(cls,args):
           '''method body'''

      def classB(cls):
         print "this is class method"

      #使用方法调用.
      classB=classmethod(classB)
  • staticmethod 用法和classmethod基本一致,如下:
  class A:

      #装饰器
      @staticmethod
      def methodA(args):
           '''method body'''

      def methodB():
         print "this is static method"

      #使用方法调用.
      methodB=classmethod(methodB)
  • iter(source, sentinel=None)

对于iter的介绍,在文档的介绍和python官方文档还是有些区别的,官方doc中的介绍如下:

iter(…)
iter(collection) -> iterator
iter(callable, sentinel) -> iterator

Get an iterator from an object.  In the first form, the argument must
supply its own iterator, or be a sequence.
In the second form, the callable is called until it returns the sentinel.

对于iter中的第一个参数定位为一个iterator or a sequence,但是在官方doc中有不同的介绍:

The first argument is interpreted very differently depending on the presence of the second argument. Without a second argument, o must be a collection object which supports the iteration protocol (the iter() method), or it must support the sequence protocol (the getitem() method with integer arguments starting at 0). If it does not support either of those protocols, TypeError is raised. If the second argument, sentinel, is given, then o must be a callable object. The iterator created in this case will call o with no arguments for each call to its next() method; if the value returned is equal to sentinel, StopIteration will be raised, otherwise the value will be returned.

为此,我进行了一个测试:

class B(object):
    pass

class A():
     def __call__(self, *args, **kwargs):
        print "[call,her,2]"

a1=iter(A(),"a")
print a1.next()
b=B()    
a=iter(b,"2")
print  a.next()
[call,her,2]
None



---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)

<ipython-input-18-6e1b318bdd62> in <module>()
      9 print a1.next()
     10 b=B()
---> 11 a=iter(b,"2")
     12 print  a.next()


TypeError: iter(v, w): v must be callable

如上,可以发现,iter(…)的要求和python官方的doc 要求一致,文档并不能完全介绍完全。当第二参数非空时,需要要求第一参数为实现类迭代功能的对象,如下会介绍(当类实现iter方法),当第二参数存在时,第一个参数必须为可调用对象(实现了call方法)。

  • len(s)

返回一个对象的长度,传入对象可以是list、string、tuple等,也可以是一个类实现了一个魔法方法(len).

  • next(…)

返回一个iterator的下一个元素,传入的对象位一个实现了next方法的对象

next(…)
next(iterator[, default])

Return the next item from the iterator. If default is given and the iterator
is exhausted, it is returned instead of raising StopIteration.

类的方法

类的方法分为类的创建方法(new),类的初始化方法(init),类的方法(classmethod),类的静态方法(staticmethod),类的方法,类的销毁方法(del),和类的魔法方法(之后介绍)如下通过一个示例介绍各个类型方法.

class Base(object):
    'a basic class demo'

    def __new__(cls, *args, **kwargs):
        print "__new__"
        return object.__new__(cls,*args, **kwargs)

    def __init__(self):
        print "__init__"



    def __del__(self):
        print "__del__"

    @classmethod
    def A(cls):
        print "class method"


    @staticmethod
    def B():
        print "static method"


    def C(self):
        print "this is self"

    def __str__(self):
        return "build-in str(o) return "

    def __del__(self):
        print "__del__"


if __name__=="__main__":
    a=Base()
    print str(a)
    try:
        print "Begin transfer-----------------------------call by instance."
        #call the class method
        a.A()
        #call static method
        a.B()
        #call the instance method 
        a.C()

        print "Begin transfer------------------------------call by Class"
        # call the class  method
        Base.A()
        # call static method
        Base.B()
        #call instance method
        Base.C(Base())
        #call instance method
        Base.C()
        pring
    except Exception as e:
        print e

    del(a)
__new__
__init__
build-in str(o) return 
Begin transfer-----------------------------call by instance.
class method
static method
this is self
Begin transfer------------------------------call by Class
class method
static method
__new__
__init__
this is self
__del__
unbound method C() must be called with Base instance as first argument (got nothing instead)
__del__
  • new 方法

**new ** 方法是一个静态方法(同时也是一种魔法方法),用于创建一个类的实例,返回一个类的实例对象用于传入初始化方法**_ init_ ** 中,一般并不需要对其进行声明和重写。若是重写的话,需要注意返回一个有效的类的实例对象,如上实例通过object父类调用类的实例化方法,用于返回一个对象实例。若是不返回一个类的实例对象,会导致类的 **_ init_ ** 方法不会被调用,当然实例(self为空)也不会被成功创建。

  • init 方法

init 是类创建过程中用的比较多的魔法方法,其是类对象创建后调用的初始化方法,紧跟者new 调用后调用,主要用于实例的变量的初始化操作,和传递类创建传入的变量,**init ** 方法可以理解为一个类的实例的构造器,其方法的特点是不会返回任何对象或者值,若返回则会抛出 TypeError 异常。

  • del 方法

同样属于魔法方法一种。如上,可以发现当我们调用del(a)来销毁实例对象时,会调用该方法,其该属类的实例的析构函数,del内建函数并不会主动调用del方法,只有当类的实例对象的引用计数为0时才会被调用,要我们主动显示的调用 del 方法完成实例的销毁操作.因此,一般不建议重写del 方法。

  • _str 方法

用于返回对象的string 字段信息,重写该魔法方法的实例可以通过调用内建函数 str(o) 来回调 str 方法。如上示例有所演示。

  • classmethod 方法

类的方法,类的方法调用层级归属类级别,其方法定义需要使用 @classmethod 装饰或者调用classmethod内建方法来实现,类的方法的第一个参数默认为类的对象,使用cls 固定表示,如上的 B方法,类的方法和静态方法一样可以通过类的实例对象调用,也可以直接通过类来调用.

  • staticmethod方法

静态方法,通过装饰器@staticmethod 或者内建函数声明使用,静态方法的方法定义部分python的一般函数定义并无不同,页不需要如同classmethod或实例方法一样传入类的对象或实例的对象,其调用和classmethod类似,可以直接通过类调用或者类的实例对象调用。

  • 实例 方法

实例方法是归属与创建的实例对象所私有,定义如上def C(self): 其方法需要传入一个实例对象self,且位置为第一个参数,该方法只能由类的实例来调用,不可以通过类直接调用(无参数),若需要通过类直接调用可以通过绑定式的方式将类的实例对象传入该方法中:** Base.C(Base()) ** 。

类的属性

类的属性部分主要分为两个小部分进行介绍:归属类或实例对象的自定义属性,归属行为特征所共有定义的魔法属性,给出一个简单的例子,根据案例说明。

class Base(object):
    CLASS_NAME="Base"
    instanceCount=0
    __instance=12
    _aa=1234

    def __init__(self,name,value):
        Base.instanceCount+=1
        self.name=name
        self.value=value

    def __str__(self):
        return "CLASS_NAME:%s,instanceCount:%s,self.name:%s,self.value:%s \n" % (Base.CLASS_NAME,Base.instanceCount,self.name,self.value)


a=Base("a",10)
print "a:[%s}\n" % str(a)
b=Base("b",12)
print "b:[%s}\n"% str(b)

print b.__dict__,"\n"
print Base.__dict__,"\n"
print Base._instance
a:[CLASS_NAME:Base,instanceCount:1,self.name:a,self.value:10 
}

b:[CLASS_NAME:Base,instanceCount:2,self.name:b,self.value:12 
}

{'name': 'b', 'value': 12} 

{'__dict__': <attribute '__dict__' of 'Base' objects>, '__module__': '__main__', 'instanceCount': 2, '_Base__instance': 12, '_aa': 1234, 'CLASS_NAME': 'Base', '__str__': <function __str__ at 0x7f7a142256e0>, '__weakref__': <attribute '__weakref__' of 'Base' objects>, '__doc__': None, '__init__': <function __init__ at 0x7f7a14190ed8>} 




---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-26-25ca76d45fc7> in <module>()
     21 print b.__dict__,"\n"
     22 print Base.__dict__,"\n"
---> 23 print Base._instance


AttributeError: type object 'Base' has no attribute '_instance'
  • 类的属性

如上,类的属性也可以认为是静态属性,可以直接通过类来调用,CLASS_NAME和instanceCount就是这样的属性.

  • 实例属性

实例属性是归属于实例对象本身的,需要直接使用实例对象来调用,如上的self.nameself.value

  • “私有属性“

python中并不存在只能从内部访问的私有变量类型,但python代码都遵守的公约规定:带有下划线(‘‘)前缀开头的变量或方法被示为飞公开API的一部分,其有两种情况,一种是前面至少有两个下划线(‘‘)开头,后面之多有一个下划线(‘‘)结束,python对其使用name mangling机制做了一个简单的支持,会将其标识符替换成_className__name,如上**__instance ** ,另一种是以一个”“开始的变量在被作为一个module导入时,使用 from module import * 后并不可以直接使用其直接使用,还是需要通过类或者实例变量配合使用.

  • 魔法属性

python中的魔法属性是对类或实例的一些数据的描述整合.如上的”dict“位一个字典映射对象,存储一个类或者实例的可读属性。类似的魔法属性还包括:classbasesnamemrosubclasses*等。

魔法方法的使用

如上,已经说了不少有关魔法方法的使用,如newinitdel等特定的类生命周期相关的魔法方法,也有功能性的如str等,如下,就是对于魔法方法做一个扩展性的说明。

魔法方法的存在是python的多态性的一种表现,不同其他语言的多态,python的多态更多的表现在动作或者称作功能上,对于想要实现某类功能的类只需要对应实现某些对应的魔法方法,即可通过python的内建函数进行某些特定功能的操作。如常见的求长度、求hash数值、迭代器、生成器的使用。如下,通过一个小的示例来了解一些常用的魔法方法。

class Base(object):
    def __init__(self):
        self.index = 0
        print "base __init__"

    # 返回字符串化
    def __str__(self):
        return "Base"
    #
    # 返回对象长度
    def __len__(self):
        return 10

    # 返回hash数值
    def __hash__(self):
        return 199908

    # 真值判断
    def __nonzero__(self):
        return True

    # 返回转化成一个unicode对象
    def __unicode__(self):
        return u'海飞'

    # 当查找一个一个属性未查找到时调用
    def __getattr(self, name):
        if name == "name":
            return "hfcai"
        else:
            raise Exception("No exists tohis attribute.")

    #当尝试给一个属性赋值时调用
    def __setattr__(self, name, value):
        self.__dict__[name] = value

    # 当属性被删除时调用
    def __delattr__(self, name):
        print "__delattr__:%s" % name

    # 新式类中访问属性的调用,使用超类的方法防止循环调用
    def __getattribute__(self, name):
        return super(Base,self).__getattribute__(name)

    # 新式类作为描述器
    def __get__(self, obj, type=None):
        return 'get', self, obj, type

    def __set__(self, obj, val):
        print 'set', self, obj, val

    def __delete__(self, obj):
        print 'delete', self, obj
    #
    #
    # 接受self[key]这样的切片操作,一般针对于序列对象
    def __getitem__(self, key):
        return self.__dict__[key]

    def __setitem__(self, key, value):
        print "__setitem__"

    def __delitem__(self, key, value):
        print "__delitem__"

    # 迭代器  ,重写表明当前类的示例为一个迭代器
    def __iter__(self):
        return self

    # next
    def next(self):
        self.index+=1
        return self.index

    # 返回一个反向的迭代对象
    def __reversed__(self):
        return [9, 8, 7, 6]

    # 含操作
    def __contains__(self, item):
        return True



a = Base()
#__contain__
print "test" in a
# __iter__
b = iter(a)
print b.next()
# __len__
print len(a)
print reversed(a)
print str(a),unicode(a)
base __init__
True
1
10
[9, 8, 7, 6]
Base 海飞

如上,涉及到的魔法方法较多,分类讲解一部分的魔法方法,其用法类似:

  • 普通关联回调内建函数

这种比较简单,在类中重写对应的魔法方法,使用对应的回调返回重写方法的返回值,大多的魔法方法都是这类的,如上lenstrunicode等就属于这类。

  • 属性相关魔法方法

与属性相关的魔法方法getattrsetattrrgetitem_setitemgetattribute,其中getitem_setitem属于序列或映射的魔法方法,而getattrsetattrr属于获取类中的变量的属性的设置获取调用情况。其中getattr 属于当类中无法获取该变量时调用,而getattribute会拦截所有属性的获取。

  • 描述器

对于实现了getsetdel魔法方法的类可以称之位描述器.同时具有getset方法,这样的descriptor叫做data descriptor,如果只有get方法,则叫做non-data descriptor。

  • 迭代器

python中的迭代器是实现了iter魔法方法的类,并通过实现 next(self)方法进行迭代调用,如上示例。

  • 生成器

python中有一个特别的迭代器,可以通过关键词yield进行迭代返回,如下格式:

def reperater(value):
    while True:
        new = (yield value)
        if new is not None:
            value=new


r=repeater(42)
r.next()

42

r.send("Hello world!")

"Hello world!"

如上demo来自《python基础教程 -生成器》一章的示例,其中包含yeild会返回一个对象,并挂起。而在挂起状态可以通过send方法发送一个值,而再次返回发送过的值.

参考

Python 中的文件操作

mediastack阅读(228)

python中对于数据输入输出的处理和常规性语言类似。主要包括:系统输入输出、文件存储、数据库存储等,其中数据存储读取操作中主要就是对于文件和数据库的处理方面。python中对于文件的处理提供了一个比较常用且比较方便的内建类file,通过file可以比较方便的对文件操作。python中对于文件的操作较多的方法可以很方便的实现文件的读取、写入、删除、查找等操作,如下示例:

#!/usr/bin/env python
#-*-encoding:utf-8-*-

import  sys,fileinput,codecs

testFile = file('testFile.txt')
# 文件读操作
# print testFile.read()
# 文件单行读操作.
print testFile.readline()
# 文件单行制定字符读操作.
print testFile.readline(3)
# 文件读所有行,并返回一个list.
# print testFile.readlines()
print "file name:",testFile.name
# 文件迭代
print testFile.next()
print next(testFile)

# 返回一个整型的文件描述符,可供底层操作系统调用.
print testFile.fileno()

try:
    testFile.write("test")
except Exception as e:
    print e

# 关闭文件
testFile.close()

# with  open(name="testFile.txt",mode='wb+',buffering=1024) as testFile:
#     testFile.write("print \"append mode------------------------------ 1\"")
#     print testFile.read()

with  open(name="testFile.txt",mode='a+') as testFile:
    testFile.write("print \"append mode------------------------------2 \"")
    testFile.flush()
    testFile.seek(0)
    for line in testFile:
        print "line:",line

# fileinput
testFile =  fileinput.input('testFile.txt') 
for line in testFile:
    print line
    testFile.close()
    break

# print testFile.filename()

# codecs
with codecs.open('testFile.txt','rb',encoding='utf-8') as testFile:
    print '\n\n\n'
    print testFile.read(10)

# print help(open)
# print file.__doc__
蔡海飞

123
file name: testFile.txt
456

pwd

87
File not open for writing
line: 蔡海飞

line: 123456

line: pwd

line: 男

line: 1992print "append mode------------------------------2 "print "append mode------------------------------2 "
蔡海飞





蔡海飞
123456
pwd

python文件操作,打开文件可以通过指定文件操作的模式类型从而赋予文件操作的不同权限,python中对于文件的模式甚至如下几个类型:

  • r
    模式’r’为读模式,一般不制定文件打开的模式时默认为读模式
  • w
    模式’w’为写模式
  • b
    模式’b‘为以二进制格式打开文件,该模式一般会和其他模式混合使用如:’rb’、’wb‘,’ab’等
  • a
    模式’a’为追加模式,一般特指写模式的追加,一般的写模式’w’执行写操作时若文件存在则直接覆盖(指针指向开始位置),若不存在则创建,而’a’模式下的文件写操作则是若文件存在,则指针指向文件结尾追加写入,若文件不存在则创建。

同时允许通过在模式后添加一个’+’来来实现文件的读写。如’r+’、’rb+’、’w+’、’wb+‘、’a+‘、’ab+‘。文件打开还有一个参数是设置文件的buffering的,当buffering为0表示不设置缓存,buffering为1则表示缓存为一行,当其他大于1的数字则表示缓存的大小。如上,文件的打开可以使用系统自带的内置类file或者内置函数open函数,也可以通过fileinput模块或者codecs(可以对文件打开设置编码)模块进行打开。

Enjoytoday

斐波拉契数列与Python

mediastack阅读(248)

习惯性的,我们每学习一个编程语言,都喜欢从数学的原理、经典数题开始我们的学习之旅,而斐波拉契数可以说是各中常客了,仿佛是没有写过斐波拉契数列就不算学了某个语言一样。这篇文章难脱俗套,也是一个“斐波拉契数列”与业界传奇Python大叔的故事。

斐波拉契的微笑

斐波拉契的微笑

铁打的斐波拉契流水的编程“大叔“[Python]

话说我们今天的女猪脚大美女”斐波拉契数列“也是出身名门响当当的人物。斐波拉契数列自从被伟大的数学家昂纳多·斐波拉契(Leonardoda Fibonacc)通过兔子的繁殖提出以来,一直都是最美丽的数列,受到万众追捧。C/C++爱她(FIB数列)、Java/js追捧,php/Python倾慕,也无愧于它黄金数列之称。那么,斐波拉契数列究竟有啥神秘的呢?

斐波拉契数列

斐波拉契数列值得是一组如下循环的数列:

1、1、2、3、5、8、13、21、34、……

一般在数学中我们可以这样对其进行表达:

F[1]=1,
F(2)=1,
F(n)=F(n - 1)+F(n - 2)(n ≥ 3,n ∈ N*)

很简单的一组数列,但却很诱人,因为专家发现,当数列无穷大的时候,斐波拉契数列的前后两个数之比无限接近与黄金分割比例:约为0.618。赞美的话我就不多说了,我们的大自然、生活无处不包裹在斐波拉契的美艳之中。

那么接下来我们就得看看Python大叔如何来描述斐波拉契的美艳不可方物。

谦卑的Python

python大叔也是心诚,想着多头并进,换着法子来描述、赞美斐波拉契。这一想起心爱的人啊,就爱如泉涌,这不,Python大叔一不留神就想出来了四种方式来表白斐波拉契。

递归方式

递归的方式也是较为常用的方式,通过逐层递进的方式来生成斐波拉契数列:

#!/usr/bin/env python 
# -*- coding:utf-8 -*-

def fbis(num):
    '''递归法实现斐波拉契数列
    '''
    result = [0, 1]
    for i in range(num-2):
        result.append(result[-2]+result[-1])
    return result

if __name__ == "__main__":
    result=fbis(10)
    for i,n in enumerate(result):
        print("第%d个数是:%d"%(i,n))

生成器

这种方式使用到了python的高级特性,可以说诚意满满:

#!/usr/bin/env pyhon
# -*- coding:utf-8 -*-

def fbis(n):
    """
    通过yield生成器实现斐波拉契数列
    """
    a, b = 0, 1
    while n > 0:
        a, b = b, a+b
        n -= 1
        yield a


if __name__ == "__main__":
    i=0
    for n in fbis(10):
        print("第%d个数是:%d" % (i, n))
        i+=1

魔法方式实现

这种方式更加突出了python 面向对象的思想,同时也突出了python魔法方法的便利性:

#!/usr/bin/env pyhon
# -*- coding:utf-8 -*-

class Fbis(object):
    """使用魔法函数实现斐波拉契数列
    """

    def __init__(self, n):
        self.n = n     # 最大数列数
        self.current = 0  # 当前位置的斐波拉契数列值
        self.a = 0  # 初始第一个位置
        self.b = 1  # 初始第二个位置

    def __next__(self):
        """next()函数调用时触发
        """
        if self.current < self.n:
            self.a, self.b = self.b, self.a + self.b
            self.current += 1
            return self.a
        else:
            raise StopIteration

    def __iter__(self):
        """返回自身
        """
        return self


if __name__ == "__main__":
    i=0
    for n  in Fbis(10):
        print("第%d个数是:%d" % (i, n))
        i+=1

矩阵实现

这种方式可以说性能有较高的提高:

#!/usr/bin/env pyhon
# -*- coding:utf-8 -*-
import numpy

def matrix(n):
    Matrix = numpy.matrix("1 1;1 0")
    return pow(Matrix, n)

def fbis(n):
    """使用numpy库实现斐波拉契数列
    """
    result_list = []
    for i in range(0, n):
        result_list.append(numpy.array(matrix(i))[0][0])
    return result_list

if __name__ == "__main__":
    i=0
    for n in fbis(10):
        print("第%d个数是:%d" % (i, n))
        i+=1

来自Python大叔的自白

Python大叔这一溜串儿操作,心中不禁自得。想着,想我这么优秀的人还哪儿能找到。那么问题来了,Python大叔哪儿优秀了?就这次告白来说我们可以看到Python大叔显而易见的几个亮点:

  • 极强的语言表现力
    这明显的在代码量上可以完美的得到表达
  • 超高的内功修养
    生成器和魔法方法强炸天有咩有~
  • 无法可说的自来熟
    和谁都能混的熟(numpy),它不需要对多高的实际功底就可以通过强大的自来熟特性让别人把它的伙计干好。

代码实现

本栏目的所有实现代码均可通过Github或码云获取,项目地址:

写在后面的话

看到这么拼命努力的Python大叔,你还有理由不喜欢它吗?那么问题来了,这么可爱的Python大叔,你还要等到什么时候才来重新它?欢迎大家来订阅,你的支持,就是我创作最大的动力!

如何学习一门新的语言–Python?

mediastack阅读(279)

在整个开发生涯,对于我们程序员而言,很难实现只需要使用一种开发语言或者开发框架的场景。我们可能由于各种各样的原因(可能是由于工作需要或者是个人兴趣),需要去学习我们的第二语言、第三语言。这时候,我们会发现,对于绝大数人而言,学习一个新的语言都是较为困难的,我们会常常发现,一本书怎么看都只能看到十几页,二十几页,又或者语言学会了,但是我真的不知道如何使用这个语言来开发一个项目。这时候,我们就需要考虑是不是我们的学习方式出现了问题。

我其实在很长一段时间都处于类似的困惑中,我发现我每天都在学习语言或者新的技术,但是也只是学了,并没有达到掌握的程度。这时,我就在想我该如何去学习?通过不断的梳理我的学习过程和开发经历,我发现想要学习一个语言,并能够较为迅速的理解它、掌握它、运用它,一般的我们需要经历如下几个过程:

语法基础学习

这部分我们需要的掌握语言或者技术的基础语法格式、关键字、变量定义使用、控制语句使用、函数、对象定义使用。这一部分是我们学习的比较快的部分,也通常是我们学习止步的部分。

数据结构学习

其实这部分和前面一部分[语法基础学习]存在一定的重合部分,但之所以我将它单独拿出来,是由于其有着与一般基础不一样的特质,这部分常用,但并不简单,看起来所有的列表、数组、元组都一样,但其实在使用上很讲究技巧,熟练的使用语言中的常用数据结构(数组、列表、元组、字典之类)能帮助我们更易于解构问题,解决问题。对我而言,这部分:基础但并不简单

文件操作

这部分属于尝试常识性学习操作,学起来不难,但学好不容易。文件的操作所涉及的知识往往都是难啃的“骨头”,如文件操作需要考虑的并发问题、压缩等问题。

网络操作与数据库连接

这是语言学习的基础,也是语言学习的难点所在,网络操作是每个语言学习的必修课,但凡涉及多端交互网络是必不可少的部分,数据库是大多数语言学习的重点,对于后台语言而说,数据库操作的优劣直接关系一个系统的优劣。

语言特性学习

这部分对于一个语言的学习而言至关重要,可以说是一个语言的灵魂,它是异于其他语言的部分,可以说这部分内容如果没有学习好,这门语言等于白学。好似Python的内置函数,Kotlin的扩展函数,Java的泛型和反射,JS的闭包等都是一个语言的精华部分。

开始一个项目

这一部分在我心中是最重要的一环。前面学的再好,如果不迈出项目开发这一步,一切都是镜中花、水中月,自己意淫罢了。其实说了这么多,我想说的就只是这一句:开始一个项目!

Python语法基础

mediastack阅读(502)

python属于解释型语言。根据python的书写顺序来介绍,python作为一个脚本语言可以直接通过支持python环境的terminal通过命令进入python编译环境,也可以通过编写后缀为.py的py执行文件(后缀并非一定,也可没有后缀)实现编译运行。python基础语法分如下几个部分介绍:python文件结构,python注释,python关键字,python变量等。

python文件结构

和一般的语言类似,python文件也被区分成几个较为明显的部分,每个部分都负责自己需要做的工作,从而达到完美编译运行python文件的目的。简单区分可以将python分为如下三个部分:

  • Executable Python Scripts 和 magic comment可执行的脚本(Executable PythonScripts),主要是使用在类BSD的Unix系统中,为了让python脚本可以直接运行而非通过python命令制定文件运行(如同shell脚本一样直接运行),需要添加一行声明注释,并将py文件添加可执行权限(x),即可直接运行该py文件,其声明如下(该行存在的话一般位于py首行):

#!/usr/bin/env python

魔法注释(magic comment),主要是用于对python文件的源码进行编译的编码设置,默认采用的ASCII编码,若需要声明成utf-8或其他类型编码则需要添加此注释。基本格式如下:

# -*- coding: utf-8 -*-

该行在如上对py的声明不存在时放在首行,否则一般放在第二行.一般完整的写法如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

  • 导入模块

对于py来说,我们需要使用系统或者三方的某些功能的话,就需要让其功能模块和该py文件建立联系或者说是一个简易的依赖引用的关系。和其他语言类型,python可以使用import 关键字引入需要使用的模块,同时可以通过”,”将多个模块同时导入。除此之外,python还可以通过 from关键字导入模块的部分数据(变量,方法等). 需要注意的是使用 import 导入的部分需要通过导入的模块名应用获取数据,而通过 from导入的数据可以直接如同在模块内部使用一样直接调用,如下示例:

#import导入格式
import sys #导入单个模块
import sys,math,cmath #导入多个模块

#from导入格式
import sys import * #导入所有的数据
import sys import path #导入sys中的变量path



#import 导入的使用
import math

if __name__ =="":
    number=45.67
    print "number去除小数:",math.floor(number)



#from 导入使用
from math import floor

if __name__ =="":
    number=45.67
    print "number去除小数:",floor(number)

如上,“#”为python 中注释开始符号,稍后会详细介绍.使用from导入模块时需要特别注意避免重复的问题。

  • 代码部分

代码部分放在如上两个部分的底部,python代码的格式是高度的敏感代码的格式的,通过空格来对代码的层次进行划分,通过代码的缩排来区分代码块。一般的对于执行一个py文件,代码通过顺序执行代码,一般的我们可以通过判断python的自有变量“name ”来判断该py当前的运行环境是属于主程序运行还是输入导入的模块(主程序运行的话该变量值为固定” main“,若是导入的模块的话,其值为该模块的名字),如:

#!/usr/bin/env python
# -*-encoding:utf-8 -*-
import sys

def main():
    pass


if __name__ == '__main__':
  main() #通过这里控制模块的测试代码.

Python注释和标准输入输出

python中的注释通过”#”实现,python中以“#”号开头的右边的所有的内容都会被忽略,于代码的运行不产生任何影响。如下:

name="hfcai"  #用户名

python中的标准输入输出有多种方式,python的输出可以分为三种种方式:一个是标准化的通过print打印输出,也可以是一个表达式返回输入,或者通过文本写入的方式输入。比较简单的是表达式返回输出和print语句(也可以理解为方法)打印输入。但有所不同的是,表达式返回输入一般存在于python执行环境,而print打印输出输入标准的输出接口返回,比较明显的是,表达式类型的输出只有我们通过控制台进入python环境才会输出,而单独运行python文件并不会产生输出内容.如下:

#表达式输出
hfcai@ubuntu:~/Desktop$ python
Python 2.7.6 (default, Oct 26 2016, 20:30:19)
[GCC 4.8.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> "test"
'test'
>>>



#print输出

#!/usr/bin/env python
# -*- encoding:utf-8 -*-

print "test"

#执行
hfcai@ubuntu:~/Desktop$python test.py
test

python的输入方式有很多中,常见的有通过系统的输入函数提示人工输入类似于C中的scanf函数,还有通过运行py文件附带参数输入,读取文件等方式,如下介绍系统输入函数。使用如下:

#input输入
age=input("How old are you ?")
print "your are %s years old." % age

#结果

How old are you ?12
your are 12 years old.

How old are you ?12*2
your are 24 years old.


How old are you ?"abc"
your are abc years old.


How old are you ?abc
Traceback (most recent call last):
  File "/home/hfcai/Projects/PythonProjects/pythonNotes/exercises/basics/basics_struct.md.py", line 13, in <module>
    age = input("How old are you ?")
  File "<string>", line 1, in <module>
NameError: name 'abc' is not defined

Process finished with exit code 1




#raw_input输入
raw_str=raw_input("get raw_input:")
print raw_str

#结果
get raw_input:23+76
23+76

get raw_input:abc
abc

如上,可以看出,raw_input将输入内容看成string,返回输入所有内容,input将输入内容识别为表达式,当输入字符串的话则需要输入字符串的定义。

Python 变量

python中可以简单的将基本变量类型非为数字类型(包括int,float等)和字符串类型,python中对于变量的赋值较为简单,并不需要申明变量的类型,python会自动识别,变量赋值语句如下:

param=1
param1=1.9
param2="character."
  • 数字

python中支持浮点型数据,整数和浮点型数据的计算会被转换为浮点型。

>>> print 1.2*2
2.4
  • 字符串

python 中的字符串可以通过单引号’test’,双引号“test”,或者三对单引号或三对双引号跨行表示。

a=‘Traceback a’
b=“hacker”
c=’’’
name:hfcai
sex:man
age:25

python 关键字

python关键字可以通过导入python中的keyword模块查看,如下:

import keyword
print keyword.kwlist


#结果
['and', 'as', 'assert', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'exec', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'not', 'or', 'pass', 'print', 'raise', 'return', 'try', 'while', 'with', 'yield']

列表、元组、字典

list,tupple,dict这是python中较为常见的数据集合,每种的使用场景有差异不同。

  • list列表

列表是一组有序项目的集合。可变的数据类型,以方括号“[]”表示的数据集合,不同成员以“,”分隔。列表中可以包含任何数据类型(包括列表等数据类型)。如下:

list = ['testa', 'bbb', 123433, 40.6]
   a = ['test', 'a', 999]

   print list
   list[3] = 3
   a.append("bb") #追加一个变量
   a.pop()     #移除地一个变量
   a.count("a") #统计变量出现的次数
   list.extend(a) #追加列表
   print list[2:3]  # 分片操作
   index=list.index(a) #检索位置
   a.insert(2,12) #向‘2’位置添加一个参数12
   print list + a
   print list * 2
  • tupple(元组)

元组是由一组有序不可变集合。以“()”表示的数据集合,其余特性基本与列表一致。

#tupple
tuple = ('tupple top',123,23.45,'tupple end')
t2 = (123.4,45,'tt',109)
print tuple
print t2
print  tuple[:4]

#tuple[3]=3  //该操作无效,元组不允许修改更新
print tuple * 2
print tuple+t2
  • dict(字典)

Dictionary无序(类似与Java中的map,通过key-value方式存储),格式通过{key:value,….}赋值。和json数据格式很相像.

#dictionary
dict = {'key1':'value1','key2':23,2:"gg"}

print dict
#print dict[0] //这种操作是不合法的
print dict[2]
print dict.keys()
print dict.values()
dict2=dict.copy()
print dict2

编码风格

每个语言都有自己的编码风格,为了方便理解,为了统一格式,python的编码风格,官网给了一个标准的编码风格指南PEP8,如下文python文档中给出的一些指导性的建议:

  • 使用4空格(space)缩进,不使用制表符(Tab键)
  • 尽量保证每行的字符数目不超过79个,有助于阅读
  • 使用空行分离各个部分代码块(类和函数等)
  • 注释尽量单独一行
  • 添加文档描述,文档注解
  • 运算符和符号左右用空格分离
  • 保持名和函数的命名一致:通常是使用驼峰命名法命名类,使用下划线小写字母命名函数和方法。始终使用self作为方法的第一个参数的名称