说点实际的,为什么要学PYTHON?

  1. 各大公司做数据分析和算法的必备和首选语言
  2. 库多库多库多
  3. 简单易学,开源免费
  4. 万能胶水语言,什么都能做

变量与基本数据类型

变量是用来存储值的,我们可以对变量的值进行修改。PYTHON中没有常量的概念

PYTHON基础数据类型有:boolean, int, string, float, double, datetime, bytes等

  1. s1 = "Hello"
  2. print(s1) # Hello
  3. s1 = "股市"
  4. print(s1) # 股市

变量的命名和使用

  • 变量名只能包含字母、数字和下划线。变量名可以字母或下划线打头,但不能以数字打头,例如,可将变量命名为message_1,但不能将其命名为1_message。
  • 变量名不能包含空格,但可使用下划线来分隔其中的单词。例如,变量名greeting_message 可行,但变量名greeting message会引发错误。
  • 不要将Python关键字和函数名用作变量名,即不要使用Python保留用于特殊用途的单词, 如print
  • 变量名应既简短又具有描述性。例如,name比n好,student_name比s_n好,name_length 比length_of_persons_name好。
  • 慎用小写字母l和大写字母O,因为它们可能被人错看成数字1和0。

注意 从编程规范的角度来看,应优先使用小写的变量名

  1. s1 = "科技股"
  2. type(s1) # str
  3. a = 6
  4. type(a) # int
  5. b = 3.0
  6. type(b) # float
  7. b1 = False
  8. type(b1) # bool
  9. a == b # False

Boolean操作:or/and/not

  1. x or y
  2. x and y
  3. not x
  1. False and True # False
  2. 26.0 < 26.2 or 26.89 > 3 # True
  3. True and False # False
  4. 27.3 > 25.89 and 27.3 < 28 # True
  5. not 5 # False

比较操作

PYTHON中的比较操作返回的结果是boolean型数据

  1. a = "逆回购"
  2. b = "800亿"
  3. a == b # False
  4. a != b # True
  5. a is b # False
  6. a is not b # True

数值类型数据

留意下面几种不怎么常见的运算符

  1. 10 // 3 # 3
  2. 10 % 3 # 1
  3. divmod(10, 3) # (3, 1)
  4. 2 ** 5 # 32
  5. abs(-6) # 6

数据类型转换

  1. # 字符串转数值
  2. s = "3.1526"
  3. float(s) # 3.1526
  4. int(s) # float形式的字符串直接转int是会报错的
  5. s = "3"
  6. int(s) # 3
  7. float(s) # 3.0
  8. # 数值转字符串
  9. num1 = 3
  10. str(num1) # '3'
  11. str("-2400") # '-2400' # 任何数值都可以转换成字符串
  12. # 数值之间转换
  13. a = 3.1415926
  14. int(a) # 3
  15. float(3) # 3.0

PYTHON数据结构

介绍四种我们经常会用到的数据结构:list/tuple/dict/set

list

列表是一种可存储任意类型数据的可修改的序列结构。列表由一系列按特定顺序排列的元素组成。你可以创建包含字母表中所有字母、数字0~9或
所有家庭成员姓名的列表;也可以将任何东西加入列表中,其中的元素之间可以没有任何关系。这是一个几乎最重要的数据结构。

列表常用的操作方法

Python 入门 - 图1

创建列表

  • 使用一对方括号创建空列表 []
  • 使用列表关键字创建 list()
  1. # 通过方括号方式创建
  2. a = ["科技股", "沪电", 27.3, False, 9.9]
  3. b = [1,2,[3,4,5]] # 列表可以内嵌列表
  4. # 通过关键字创建
  5. c = list([1,2,3]) # 这种方式也需要中括号包裹
  6. d = list("abc") # 注意通过字符串创建列表的特殊形式

访问元素

  • 直接通过索引位置来访问
  • 切片形式 [startPython 入门 - 图2step],默认情况下步长省略,前闭后开
  1. # 通过索引来访问,从0开始
  2. a = [1,2,3,4,5]
  3. a[0] # 1
  4. a[-1] # 5
  5. len_a = len(a) # 获取元素的长度
  6. a[len_a] # 报错
  7. # 切片形式
  8. a[:] # [1, 2, 3, 4, 5]
  9. a[1:] # [2, 3, 4, 5]
  10. a[2:4] # [3, 4]
  11. a[0:5:2] # [1, 3, 5]
  12. a[0:5:1] # [1, 2, 3, 4, 5]
  13. a[::3] # [1, 4]
  14. a[::-1] # [5, 4, 3, 2, 1]
  15. # 当步长为-1时,与reverse方法类似,不过reverse方法改变了元素本身
  16. print(a) # [1, 2, 3, 4, 5]
  17. a.reverse()
  18. print(a) # [5, 4, 3, 2, 1]

添加元素

  • append,在列表尾部添加
  • extend,把整个列表打平了
  • insert,可以指定插入的位置
  1. # append的用法
  2. x = ["科大讯飞", 32.761]
  3. x.append(2400) # ['科大讯飞', 32.761, 2400]
  4. a = [1, 2, 3]
  5. a.append(x) # [1, 2, 3, ['科大讯飞', 32.761, 2400]]
  6. # extend的用法
  7. b = [4, 5, 6]
  8. b.extend(x) # [4, 5, 6, '科大讯飞', 32.761, 2400]
  9. # insert的用法
  10. c = [32, 3, 33.3]
  11. c.insert(0, 60000) # [60000, 32, 3, 33.3]

删除元素

  • remove,不去重
  • del 索引,[startPython 入门 - 图3step]
  • pop,返回结果(最常用)
  1. # remove用法
  2. c_ = [1,1,2,3,4,5,5,6]
  3. c_.remove(5) # [1, 1, 2, 3, 4, 5, 6]
  4. # del用法
  5. del c[-1] # [1, 1, 2, 3, 4, 5]
  6. del c_[2:3] # [1, 1, 3, 4, 5]
  7. del c_[0:5:2] # [1, 4]
  8. # pop用法
  9. c_.pop() # [1]

排序列表

  • sort方法,原结构发生变化
  • sorted函数,原结构不变
  1. # sort排序
  2. L1 = [32, 48, 35, 32.761, 33.21]
  3. L1.sort(reverse=False) # [32, 32.761, 33.21, 35, 48]
  4. # sorted排序
  5. L2 = [32, 48, 35, 32.761, 33.21]
  6. L3 = sorted(L2) # [32, 32.761, 33.21, 35, 48]

注意

  • 列表与数字的乘法运算是duplicate的
  • 列表与列表的加法运算是简单堆叠而不作计算
  1. [1, 2] * 3 # [1, 2, 1, 2, 1, 2]
  2. [1, 2] + [4, 5, 6] # [1, 2, 4, 5, 6]

tuple

元祖的格式和用法几乎和列表一致,唯一的区别就是元祖是不可更改的序列,因此你只能从元祖中查找元素,但是不能修改元素。

元祖的创建

  • 使用一对圆括号:( )
  • 使用tuple关键字:tuple()
  1. # 创建
  2. b = ("a","b", 12)
  3. c = tuple([27.3, False])
  4. # 增删改查能做的操作就只有访问了
  5. # 访问方式同list一样
  6. c[-1] # False
  7. b[0:2] # ('a', 'b')

统计单词个数

  1. name = input("Enter file:")
  2. if len(name) < 1 : name = "input.txt"
  3. fhand = open(name)
  4. counts = dict()
  5. for line in fhand:
  6. words = line.split()
  7. for word in words:
  8. # find the value that key is word, if not, return 0
  9. counts[word] = counts.get(word, 0) + 1
  10. lst = list()
  11. for key, val in counts.items():
  12. lst.append( (val, key) )
  13. lst.sort(reverse = True)
  14. for val, key in lst[:10]:
  15. print (key, val)

字典

字典是以键值对(key-value)的形式存储数据,可以在O(1)的时间复杂度上查找数据,可以认为是当前最快的速度了!

字典里的内容用“,”隔开,每个元素是键值对,”:”前的元素为key,这是唯一值不可重复的,”:”后的元素为value

创建字典

  • 大括号{}形式,类似于json的创建
d = {"name":"jeff", "age":24, "sex":"male"}
len(d)                        # 3

字典中获取元素

  • 直接通过索引来访问
  • 通过get方法
d['age']                    # 24
d['family']                    # key不存在,程序会报错

d.get('age')                # 24
d.get('family')                # 通过get方式可避免报错

字典中添加元素

  • 直接通过索引进行添加即可
d['心情'] = "happy"

字典中删除元素

  • 通过pop方法来进行删除
d.pop("心情")                # 'happy'

字典的遍历

# 遍历键-值对,获取key/value
for k,v in d.items():
    print(k)
    print(v)


# 遍历所有的键
for k in d.keys():
    print(k)


# 遍历所有的值
for v in d.values():
    print(v)


# 有序遍历所有的键
for k in sorted(d.keys()):
    print(k)


type(d.keys())            # dict_keys

set

set是key的集合,与字典类似。但是它不存储value,set中没有重复值,这几乎是它最重要的一个属性。

回忆一下我们高中学的并集与交集知识,set可以直接被用来计算这样的逻辑

集合的创建

C = [22, 28, 32, 35]
t = set(C)                # {22, 28, 32, 35}
d = set([2019, 12])        # {12, 2019} # 注意,输出的结果是无序的

查找两个集合的并集和交集

a = set([1,2,3,4,5,6,7])
b = set([1,4,5,6,10,20,3])
a | b                          # {1, 2, 3, 4, 5, 6, 7, 10, 20}
a & b                        # {1, 3, 4, 5, 6}

添加删除操作

a.add(10)
a.remove(2)

PYTHON条件判断与循环

if语句

每条if语句的核心都是一个值为True或False的表达式,这种表达式被称为条件测试。 Python
根据条件测试的值为True还是False来决定是否执行if语句中的代码。如果条件测试的值为True,
Python就执行紧跟在if语句后面的代码;如果为False, Python就忽略这些代码。

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


if price > 27.3 and price < 28.0:
    print("盈利")
elif price > 26.2:
    print("亏损1500")
elif price > 25.89:
    print("亏损2400")
else:
    print("亏到家了")

for循环

for循环语句用来遍历集合中的每一个元素,用法简单。我们在之前遍历字典中已经使用过该方法

a = [25.89, 26.2, 27.3, 28]
for i in a:
    print(int(i))

a = "科技股"
for i in a:
    print(i)

while循环

当条件满足while的设定时,代码块会一直执行下去,除非不再满足条件。while是最容易导致死循环的,所以一定要仔细检查

price = 9.9
while price >= 9.5:
    print(price)
    price -= 0.1

可以看到我们一定会给条件变量设定一个自增量,否则就会导致死循环!

break与continue

  • 要立即退出while循环,不再运行循环中余下的代码,也不管条件测试的结果如何,可使用
    break语句。 break语句用于控制程序流程,可使用它来控制哪些代码行将执行,哪些代码行不执
    行,从而让程序按你的要求执行你要执行的代码.
  • 要返回到循环开头,并根据条件测试结果决定是否继续执行循环,可使用continue语句,它
    不像break语句那样不再执行余下的代码并退出整个循环.
while True:
    balance = input("请输入预亏损:")
    balance = int(balance)
    if balance > 500 and balance < 1000:
        break

执行

请输入预亏损:300
请输入预亏损:500
请输入预亏损:999

input用户输入

函数input()让程序暂停运行,等待用户输入一些文本。获取用户输入后, Python将其存储在
一个变量中,以方便你使用。

函数input()接受一个参数:即要向用户显示的提示或说明,让用户知道该如何做。用户输入完毕后,敲击回车键即可结束程序!

mood = input("请输入你今天的心情:")
print(mood)

执行

请输入你今天的心情:笑脸
笑脸

input函数返回的结果都是字符串,因此如果你需要其他类型的数据需要注意转换

PYTHON函数

定义函数

Python中的函数主要分为两类,一类是build-in Function(内置函数)例如int(), float(), type(), max()等,另一类是user-define Function(用户自定义函数),我们主要介绍自定义函数。

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

a = 3
def my_fun(a):
    c = 1
    print('你赚了' + str(a + c) + '元')

my_fun(-5000)                                    # 赚了-4999元

也存在作用域的概念,有点类似于JavaScript

a = 3
b = 4
def my_fun1():
    print(a + b)

my_fun1()                             # 7

return 用于返回函数的结果,当然函数也可以不返回结果,那么此时就可以不使用return. 注意return可以同时返回多个值,调用函数的时候需要用等数量的变量来传递值

def my_fun(x, y, z):
    return x + y + z, x * y * z

r1, r2 = my_fun(2, 3, 4)
print(r1, r2)                        # 9 24

函数的参数

PYTHON函数的定义方法非常简单,但是却很灵活,尤其是对参数的设定,可以多种多样。 除了正常的定义的必选参数外,还可以使用默认参数、可变参数和关键字参数。

位置参数

位置参数可以理解为我们要按照参数的位置顺序传递值,这是最简单最常用的函数参数

def my_fun0(age, name, home):
    if age > 18:
        print(name, home)

my_fun0(25, 'Jeff', 'HZ')            # Jeff HZ

# 错误的传递
my_fun0("Jeff", 25, "HZ")

# 或者通过指定参数名称来传入值,这样就不需要考虑顺序
my_fun0(name = "Jeff", age = 25, home = "HZ")

默认参数

编写函数时,可给每个形参指定默认值。在调用函数中给形参提供了实参时, Python将使用
指定的实参值;否则,将使用形参的默认值。因此,给形参指定默认值后,可在函数调用中省略
相应的实参。使用默认值可简化函数调用,还可清楚地指出函数的典型用法。

def my_fun0(age, name, home = "杭州"):
    if age > 18:
        print(name, home)

my_fun0(25, 'Jeff')                # Jeff 杭州

# 修改默认参数的值
my_fun0(40, "Tom", "Japan")        # Tom Japan

注意:默认参数在参数列表中一定是置于最后的

可变参数

可变参数顾名思义就是传入的参数个数是可变的,可以是任意的。

假设我们需要定义一个函数计算一下:1x1 + 2x2 + 3x3 + 4x4,可以传入一个只保存[1,2,3,4]的列表或者元素参数,如下所示:

def my_fun(x):
    r = 0
    for i in x:
        r = r + i * i
    return r

x = [1, 2, 3, 4]
my_fun(x)

但是每次调用都需要预先组装一个列表或者元祖,有点麻烦。或者如果每次我们调用函数的时候都计算不同的n呢?那我们得组装不同的n个列表。我们尝试使用可变参数来看一下:(形参前加*号)

def my_fun1(*x):
    r = 0
    for i in x:
        r = r + i * i
    return r

my_fun1(1, 2, 3, 4)                    # 30
my_fun1(1, 2)                        # 5
my_fun1()                            # 0

可以看到我们仅仅是在参数前面加上一个星号*,里面的计算逻辑完全不改变,就能实现之前说的可变想法,其调用也不需要再额外组装列表,函数内部会把参数作为一个tuple来进行使用

如果我们已经有了一个列表[1,2,3,4],我们怎么计算上述所说的公式呢? 来看一下可变参数的强大之处(实参前加*号,list/tuple转换):

a = [1, 2, 3, 4]
my_fun1(*a)                    # 30

关键字参数

关键字参数可以传入任意个带有参数名的参数,这些参数会在函数内部组装成一个字典格式,用两个*号的格式表示.

def my_fun2(name, **kv):
    if name == "Jeff":
        for k, v in kv.items():
            print(k, v)

fun2 = my_fun2("Jeff", age = 25, sex = "male", home = "郑州")

执行

age 25
sex male
home 郑州

函数my_fun2除了一个必选参数name之外,还接受了一个关键词参数kv,我们在函数内部把它当做一个字典进行使用

参数组合

在Python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数,这4种参数可以组合使用。但是请注意,参数定义的顺序必须是:必选参数、默认参数、可变参数、关键字参数。

def complex_fun(name, home = "郑州", *args, **kv):
    if name == "Jeff":
        r = 0
        for i in args:
            r = r + i
        print(r)
    elif name == "Peter":
        for k, v in kv.items():
            print(k, v)
    else:
        print("不认识: " + str(home))

a = [1, 2, 3, 4] 
complex_fun("Jeff", "HZ", *a, age=18, sex="male")
complex_fun("Peter", "HZ", *a, age=18, sex="male")

执行

10
age 18
sex male

注意:如果可变参数前有默认参数,且没有被赋值,那可变参数拆包后会先赋值给默认参数,剩余部分才会被打包成tuple

# 这两个函数是等价的效果,这里的home被赋值了1
complex_fun("唐三", *a, age=18, sex="male")            # 不认识: 1
complex_fun("唐三", 1, 2, 3, 4, age=18, sex="male")   # 不认识: 1

函数编写规范

编写函数时,需要牢记几个细节。应给函数指定描述性名称,且只在其中使用小写字母和下划线。描述性名称可帮助你和别人明白代码想要做什么。给模块命名时也应遵循上述约定。

每个函数都应包含简要地阐述其功能的注释,该注释应紧跟在函数定义后面,并采用文档字符串格式。文档良好的函数让其他程序员只需阅读文档字符串中的描述就能够使用它:他们完全可以相信代码如描述的那样运行;只要知道函数的名称、需要的实参以及返回值的类型,就能在自己的程序中使用它。

PYTHON列表生成器

列表生成器是python内置方法却又非常强大的功能,我们在处理数据的时候一定要灵活掌握该方法。

列表生成器一般把元素写在前面,后面使用for循环读取每一个元素

通过一个例子来解释一下什么是列表生成器:

假设要生成一个[1, 2, 3, .., 100]的列表,可通过下列方式实现

# range前闭后开,生成某个范围内的整数
list(range(1, 101))

假设要生成一个 [1 1, 2 2, …, 100 * 100]的列表呢?

[x * x for x in range(1, 101)]

还可以接上if语句进行判断,上面的列子,我们只生成能被2整除的元素列表

[x * x for x in range(1, 101) if x % 2 == 1]

更复杂的,我们可以嵌套多个循环,但是一般来说两层循环就够了

a = [1, 2, 3, 4, 5]
b = [10, 20, 30, 40, 50]
[i * j for i in a for j in b]

PYTHON面向对象

PYTHON是一门面向对象的语言。类(class)是一种抽象的模板,实例(Instance)是根据类创建出来的具体对象,每个对象都有相同的方法,只不过传入的数据可能不同。

类里面一般包含属性和方法,你可以简单理解为属性是静态的,方法是动态的。比如人(Person)这个类,嘴、手、腿就是类的属性,跑步、吃饭等就是类的方法。一般类的首字母大写。

我们可以把在创建实例时我们认为必须绑定的属性强制填写进去,这里通过 init 方法完成。init 方法的第一个参数永远是self,代表了实例本身。有了该方法之后,在创建实例的时候必须强制指定属性值,否则会报错。该方法也可以理解为初始化的一个动作,在创建实例的时候初始化该实例的一些属性!

class Person:

    home = 'HZ'     # Shared by all instances

    def __init__(self, head, legs, character):
        self.head = head
        self.legs = legs
        self.character = character
        self.shoes = "big"

    def getLegs(self):
        print(self.legs)

# 创建实例
p1 = Person("big head", "long legs", "outgoing")
p1.getLegs()                # long legs
print(p1.home)                # HZ

继承和多态

我们可以定义一个class类,然后再定义它的子类,这个子类继承了上面的类,被继承的类称作父类,有点像现实生活中的父与子,儿子继承了父亲的全部遗产。

简单继承

class Person:

    def __init__(self, head, tummy, legs, feet):
        self.head = head
        self.tummy = tummy
        self.legs = legs
        self.feet = feet
        self.character = "great"

    def getCharacter(self):
        return self.character


class Adult(Person):
    pass                    # pass 占位符程序 to do it later

Adult类继承了Person类,Person类就是父类。

继承的好处就是子类可以享用父类的全部方法和属性。虽然Adult什么也没定义,但是可以直接使用Person的方法

ad = Adult("大头", "小肚子", "长腿", "小脚")
ad.getCharacter()            # great

子类初始化父类

子类也可以有自己的初始化方法,一定要用 super().init() 去初始化父类

函数super()将返回当前类继承的父类,然后调用init()方法.

class Adult(Person):

    def __init__(self, head, tummy, legs, feet, job):
        super().__init__(head, tummy, legs, feet)
        self.job=job

    def getJob(self):
        return self.job

    pass

adult = Adult("大头", "小肚子", "长腿", "小脚", "数据分析")
adult.getJob()                # 数据分析

方法重载

简单来说,就是子类重写了父类的一个同名方法,看下面例子的输出结果

class Adult(Person):

    def __init__(self, head, tummy, legs, feet, job):
        super().__init__(head, tummy, legs, feet)
        self.job=job

    def getCharacter(self, default = 'outgoing'):
        return default

    pass

adult = Adult("大头", "小肚子", "长腿", "小脚", "数据分析")
adult.getCharacter()        # outgoing

PYTHON动手试一试

运行 import this 命令,仔细阅读PYTHON之禅,理解PYTHON编程简单之美!

import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!