Python基础

Python 运行机制

程序运行主要有两种机制:编译型和解释型。编译型是将代码(源文件)通过编译器,编译成机器码文件,当运行的时候直接执行机器码文件,例如 C 语言;解释型是将源文件通过解释器,逐行进行翻译并运行。

Python 则属于解释型的语言。

编译型和解释型语言各有优缺点:

  • 解释型:

缺点:执行慢
优点:可以跨平台(操作系统)

  • 编译型:

缺点:不能跨平台
优点:执行快

基础知识

输入输出

先说两个最基本的函数:输入和输出。

输出函数 print (),语法就是:

print(要输出的内容)

输入函数是 input (),功能是接收用户输入的内容,语法是:

input(输出的内容)

在 Python 里,“#” 表示注释,“#” 后面的东西不会被执行。

变量

变量就是一个名字,需要先赋值在使用,变量要符合标识符 (名字) 的命名规范,这是硬性要求,标识符相当于名字,包括变量名、函数名、类名等等

  • 标识符的命名规范
  1. 合法的标识符:字母,数字 (不能开头), 下划线,py3 可以用中文(不建议),py2 不可以。
  2. 大小写敏感。
  3. 不能使用关键字和保留字。
  4. 没有长度限制
  5. 望文生义

数据类型

数据类型可分为以下 6 类:

(1) 整型:整数,英文名 int ,例如 5 的数据类型就是整型。

(2) 浮点型:小数,英文名 float ,例如 0.5 就是1个浮点型数据。科学计数法,e表示乘以10几次方,例如

b=1e10 表示1*10的10次方。

(3) 字符串:英文str,表现形式有4种:‘xs’ 、 “xs” 、 “”“xsxs”“” 、 ‘’‘‘xxx’’’

三引号有个特殊功能,表示注释,跟 # 一样的功能,例如:

"""
xsx
xs
这里面的都是注释内容
"""

(4)布尔类型:英文bool,True为真,False为假;1表示真,0表示假。

(5)None 是一个单独的数据类型。

(6)列表、元组、字典、集合也是常见的数据类型。

常用的获取数据类型信息的函数有 type ( ) 和 isinstance ( ) 两个。

(1)type( )

语法是 type (对象) ,返回的是对象的类型,前面我们也有用过,但是它是在内部返回的,如果你不输出它你是看

不到的,所以经常会和输出函数 print ( ) 嵌套使用。

(2)isinstance( )

isinstance ( ) 常用来判断数据类型,它返回的是布尔值(True 或 False),语法是 isinstance (对象,class) 。

for循环

for 循环和 while 循环都是循环语句,但不一样的点在于 for 循环是技术循环。

语法:

l=[3,2,1]
for 变量 in 可迭代对象:
	代码块

例子:

l=[3,2,1]
for n in l:
	print("1")

执行:

1
1
1

l 是个列表,后面我们会讲,列表里面有 3 个元素,每执行一次 for 循环,列表里面的元素就会被赋值给 n,直到列表里面没有了元素可赋值,则 n 就跳出了列表,此时的 for 循环就不成立了,不执行 for 里面的代码块。

for 循环经常会搭配 range 来使用,range 是一个可迭代对象,range 的语法如下:

range(start=0,stop,step=1)

start 值的是开始下标。range 序列里面的所有元素都有下标,第一个元素的下标是 0,所以,默认是从 0 开始。

stop 是结束位置。结束的位置下标为(元素个数 - 1),例如 range 里面有 4 个元素,那么结束下标最大为 3, 大于

3 则跳出 range。

step 是步长,如果 step 是 2,那么每次会隔开 1 个元素,默认步长为 1,即每个元素都会取到。

举例:

for i in range(8):	#可以不写star和step,但结束位置一定要写的
    print(i)
print("---------")
for i in range(10, 2, -2):
    print(i)

执行结果:

0
1
2
3
4
5
6
7
-------------
10
8
6
4

通过第一个 for 循环可以看出,range () 的第一个元素的下标是从 0 开始,而不是从 1 开始;range () 可以不写开始下标和步长,但一定得有结束位置;第二个 for 循环可以看出步长可以为负数,用于递减。

列表 (List)

列表是可以存放任何数据,包括整型,浮点型,字符串,布尔型等等,是常用的数据类型之一。

列表也是一个可迭代对象

    l = [1,2,3,4,5] ---整型列表

    l = ["a","b","c"] ---字符串列表

    l = [True,False,1>2,5<6] ---布尔列表

   	l = [1,2.5,"a",True] ---混合列表

   	l = [] ---空列表

列表是有下标的,并且下标从 0 开始,元素是指列表中每个数据,例如 l = [5,4,3,2,1] 里面有 5 个元素,但 5 的下标为 0,1 的下标为 4。

列表交换数据,对指定下标的元素进行数据交换。

例如把 [1, 2, 3, 4, 5] 里面的下标为第 2 和第 3 的元素进行数据交换:

l = [1, 2, 3, 4, 5]  # 下标/索引:0开始
l[2], l[3] = l[3], l[2]
print(l)
执行结果:
[1, 2, 4, 3, 5]

修改列表中的元素方法其实很简单,直接用这个方式就可以了:

变量[下标]=新值

例如:

l = [1, 2, 3, 4, 5]
l[2]=6
print(l)

执行结果:

[1, 2, 6, 4, 5]

切片操作

切片,顾名思义就是把 1 个列表切分为多个列表,语法如下:

变量[起始下标:结束下标] 	#结束下标取不到
l = [1, 2, 3, 4, 5]
print(l[0:4])
执行结果:
[1, 2, 3, 4]

做切片操作时要注意以下几个点:

①如果下标从0开始可以省略不写,例如 n = l[:4]
②如果结束下标取的是最后一个元素,可以省略不写,例如 n = l[3:]
③如果列表中的元素都要,开始和结束下标都可以省略,例如 n = l[:]
④n = l[:-1] 表示从0开始 - 到数二个元素

n = l [开始:结束:步长] ,这个方法既可以正向去操作列表,也可以反向去操作列表,例如:

l = [1, 2, 3, 4, 5]
n = l[-1:-3:-1]
print(n)
执行结果:
[5, 4]

元组(tuple)

元祖也是 Python 中常见的数据类型之一,它可以用来存放任何数据类型,但它也有它的特点:

  1. 不能修改,不可变类型
  2. 用( )的形式
  3. 元组也是可迭代对象
  4. 元组是有序的,下标操作,支持切面操作[ : ]
  5. 元组的创建及访问
  6. 创建:
    直接创建,例如 t = (1,2,3,4,5)
  7. 访问:
    t[下标] #获取元素
  8. 切片操作:
    t[ : ] 返回元组
t = (1, 2, 3, 4, 5)
print(t[2]) #输出下标为2的元组元素
n = t[2:4]  #切片,范围是下标2~4
print(n)
执行结果为:
3
(3, 4)

元组是不可变类型,不能修改,但是可以通过将元组转换成列表的形式进行修改和删除等操作,最后再将列表转换成元组,完成元组的修改和删除。

例如:修改元组中的元素

t = (1, 2, 3, 4, 5)
l = list(t) #将元组转换成列表
print(l)    #输出列表
l[2] = 6    #列表指定元素的修改
print(l)    #输出新列表
t = tuple(l)    #列表转换成元组
print(t)

[1, 2, 3, 4, 5]
[1, 2, 6, 4, 5]
(1, 2, 6, 4, 5)

删除元组中的元素可用 del t [下标] 方法,前提还是一样的先将元组转换成列表,例如:

t = (1, 2, 3, 4, 5)
l = list(t) #将元组转换成列表
print(l)    #输出列表
del l[2]    #列表指定元素的删除
print(l)    #输出新列表
t = tuple(l)    #列表转换成元组
print(t)

[1, 2, 3, 4, 5]
[1, 2, 4, 5]
(1, 2, 4, 5)

字典(dict)

字典是用来存储数据的,字典中的数据以映射关系存储。

字典的特点

1. 字典是Python中唯一的映射类型
2. 字典是无序的
3. 字典是可迭代对象
4. 字典的构成
   键:key
   值:value
   映射:键映射值
   键-值:键值对,又叫项 

创建字典

d = {} #空字典. d = {“name”:“不良人”,“apple”:“苹果”}

dict() 例如:d = dict() #空字典

dict(可迭代对象)

d3 = dict([("one",1),("two",2)])
print(d3)
执行结果:{'one': 1, 'two': 2}
这就是一个元组,one 是键,1 是值, ‘one’ : 1 是键值对。

dict(**kwargs)

d4 = dict(a=3, b=4)
print(d4)
执行结果:
{'a': 3, 'b': 4}

字典访问

  1. 基本形式
变量名[键名] #键所对应的值
d = {"name": "小黑"}
print(d["name"])
执行结果:
小黑
  1. 添加一个键值对
    变量名[键名]=值
  2. 修改一个键值对的值
    变量名[键名]=值

函数

函数是由一组代码组成,完成某个特定的功能。

def 函数名(参数): 
	代码块(函数的实现/函数体)

参数相当于变量,参数可以为 1 个或者多个,用逗号隔开,还可以没有参数,等于无参;代码块是函数的实现,又叫函数体。

函数的运行机制

函数的运行遵循以下机制:

从函数调用开始执行

通过函数名字找到函数定义的位置(创建函数的位置)

执行函数体

执行完毕之后,返回到函数的调用处

函数的特点
通过上面的例子可以发现,函数具有以下特点:

避免了代码的冗余
提高了代码的可维护性
提高了代码的可重用性
提高了代码的灵活性

函数的参数

形式参数:形参
	在定义函数的时候传递的参数
实际参数:实参	
	在调用函数时传递的参数
无参
	没有任何参数
	
默认参数: 给了默认值的参数--形参 如果传递了新的值,那么默认值就被覆盖了

位置参数和关键字参数混用: 当位置参数和关键字参数混用时,位置参数在前

关键字参数: 用形参的名字作为关键字来指定具体传递的值,则在函数调用时,前后顺序将不受影响。

位置参数:实参的位置和形参一一对应,不能多也不能少。

可变成参数: def 函数名(*a) 本质上封装成了元组

可变成参数:def 函数名(**kwargs) 将参数封装成了字典

可变成参数和位置参数混用的时候:可变参数优先

函数的文档

写代码的时候我们经常需要写文档,前面有提过 #和三引号可以进行代码的注释,但在这里要介绍一种新的方法,也是写代码时常用的函数文档书写格式:在函数体的第一行用 “”““”” 进行文档说明,这是标准化的函数文档书写。

拥有函数说明文档之后,就可以获取函数的文档内容,方法是:

函数名.__doc__

函数的返回值

关键字:return
返回值谁调用就返回给谁

任何函数都有返回值

如果不写return ,也会默认加一个return None

如果写return ,不写返回值 也会默认加一个None

可以返回任何数据类型

return后面的代码不在执行,代表着函数的结束

函数的变量的作用域

局部变量
定义在函数内部的变量
先赋值在使用
从定义开始到包含他的代码结束
在外部无法访问

全局变量

​ 定义在源文件的开头

​ 作用范围:整个文件

​ 局部变量和全局变量发生命名冲突时,以局部变量优先

global

​ 声明全局变量

nonlocal

​ 声明的是局部变量

内嵌函数

定义在函数内部的函数叫做内嵌函数(或者叫内部函数),内部函数的作用范围:从定义开始到包含给他的代码块结束在内部函数中不能进行 a+=1,a=a+1 这样的操作,解决方案是 nonlocal 和 global。

闭包

闭包是函数式编程的重要语法结构。

编程范式:一种编程范式,对代码进行提炼和抽象概括,使得重用性更高

如果内部函数调用了外部函数的局部变量,并外部函数返回内部函数的函数对象(函数名)

闭包是有条件的:

1. 必须是一个内嵌函数
2. 外部函数必须返回内部函数的函数对象
3. 内部函数必须使用外部函数的局部变量

lambda 表达式

  1. 匿名函数
    没有名字的函数

  2. 使用时机:
    只使用一次的时候

  3. 语法:
    关键字: lambda
    lambda 参数1,参数2:返回值

  4. lambda的书写形式更加的简洁,优雅
    l = lambda x:x
    print(l(100))

  5. lambda的优先级最低

面向对象

类是产生对象的模板,类就是对象的抽象化,对象是类的具象化。

创建类:

#创建Student类
class Student:
    name = "小明"	#学生类的name属性
    age = 18	#学生类的age属性
    def learn(self):	#学生类的learn方法
        print("学生的学习方法被调用了")

#创建Student类的对象
s1 = Student() #Student()就是创建的1个类对象,只是便于简写,我把它传给了s1
s1.learn()	#对象的方法
print(s1.age)	#执行对象的属性

#上面这两行代码其实可以直接写成Student().learn() ,也同样是利用类创建了对象并调用对象的方法

执行结果:
学生的学习方法被调用了
18

对象的属性和类的属性

1. 类属性定义在类的内部,任何方法之外
    	1. 创建类的时候直接创建
     	2. 类名.新的属性名=属性值
2. 使用类属性:
   	1. 对象.类属性
   	2. 类.类属性
3. 类属性的特点:
   	1. 类属性是属于类对象的
   	2. 对象共用类属性。如果类属性变化,所有的对象也会改变
4. 类属性有且只有一份,牵一发而动全局

对象属性定义在方法内部
1. 创建
		1. 对象.实例属性名=属性值
		2. 方法内部创建:self.属性名 = 属性值
2. 使用对象属性
		对象.实例属性名
3. 对象属性各自拥有互相独立
4. 对象属性和类属性发生命名冲突
		1. 以对象属性名优先
		2. 对象属性名会遮蔽同名的类属性

类方法的声明

def 函数名(self,参数1,参数2....

self

1.self默认传递,不需要传值
2.self指代的是当前的实例(对象)
3.一定会有self传递,但名字不一定必须叫self,可以叫aa
4.self后面可以跟多个参数,用“,”隔开

方法的调用

1.对象.方法名(自动传递对象),例如 s2.fun1()

2.类名.方法名(类名()) #“类名()”相当于创建对象

注:方法的调用与函数类似,谁调用就返回给谁

初始化的方法(特殊的类的方法)

def __ init __( ):

1.这个方法不需要被调用,只要创建对象就会自动执行
2.这个方法只能返回None值,无法返回其他类型的值
3.如果要给init传递多个参数,只能通过 类名(多个参数) 的方式去传递
4.如果类里面没有定义init,默认去调用父类
5.如果类里面重复定义了多个init方法,会被最后一个init方法覆盖

举例:创建对象,查看默认执行的 init 并传递多个值;调用 1 个类的方法,确认该方法被调用并执行传递的值。

#创建类
class Student:
    name = "小莫"
    age  = "18"
    def __init__(self,aa,bb):
        print("init被调用了")
        print(aa)
        print(bb)
    def fun1(self):
        print("函数1")
        print(self)
    def fun2(self):
        print("函数2")

Student.fun1(Student(100,200)) #创建对象并传递多个值给init
执行结果为:
init被调用了
100
200
函数1
<__main__.Student object at 0x000001DAD8168400>#self值的存储地址

三大特性:封装、继承、多态

封装

  1. 对象都有明确的边界,把属性和方法保护在边界之内。(安全性)

  2. 封装的力度适中。

  3. 封装的原则

(1)将不需要对外提供的内容进行隐藏。
(2)隐藏属性,提供公共的方法对其访问
		私有属性:__name="xxx"

继承

继承是父类与子类的关系

1)定义形式(类的完整形式)

	class 子类的类名(父类的类名):
		属性
    方法

2)父类:基类,超类

	object————顶层类
    如果对象没有书写继承关系,默认继承object

3)继承的特点

  • 子类可以继续父类的属性和方法
# 定义父类
class A:
    name1 = "父类的属性1"

    def aa(self):
        print("父类的方法1")

# 定义子类
class B(A):
    name2 = "子类的属性1"

    def bb(self):
        print("子类的方法1")

n = B()
print(n.name2)	#调用子类的属性
n.bb()	#调用子类的方法
print(n.name1)	#调用父类的属性
n.aa()	#调用父类的方法

执行结果为:
子类的属性1
子类的方法1
父类的属性1
父类的方法1
  • 可扩展性。父类扩展了,子类也得到扩展。

  • 如果子类没有构造方法,对象会去调用父类的。

  • 如果子类有自己的构造方法,则不会去调用父类的。

  • 子类的构造方法可以调用父类的构造方法,调用可以有以下两种方式:

父类的类名.__init__(self)	#手动传递self
super().__init__()	#不需要加self

多继承
一个子类可以继承多个父类

# 定义父类A

class A:
    name_a = "父类A的属性1"
    def aa(self):
        print("父类A的方法1")

# 定义父类B

class B:
    name_b = "父类B的属性1"
    def bb(self):
        print("父类B的方法1")

#定义子类C
class C(A,B): #继承两个父类
    pass #跳过

n = C()
print(n.name_a)
print(n.name_b)
n.aa()
n.bb()

执行结果为:
父类A的属性1
父类B的属性1
父类A的方法1
父类B的方法1

注:多继承有好有坏,优点是增强了可拓展性,缺点则是继承关系复杂之后容易混乱逻辑,难看懂,同时也会占用大量资源,比如著名的钻石继承问题。

4)方法覆盖

子类中的方法与父类中的方法同名,则覆盖父类。

#定义父类
class Animal:
    def eat(self):
        print("动物会吃东西")

#定义子类狗
class dog(Animal):
    def eat(self):
        print("狗会吃东西")

d = dog()
d.eat()

执行结果为:
狗会吃东西
  • 子类覆盖了覆盖的方法之后,本质上并没有替换父类的方法,父类的方法依然存在并可以给其他子类调用。

子类覆盖了覆盖的方法之后,本质上并没有替换父类的方法,父类的方法依然存在并可以给其他子类调用。

  • 方法覆盖的前提:子类的方法名必须和父类的完全相同

5)方法重载

出现多个方法名一样的方法(函数),Python 中通过默认值进行方法重载。

多态
多态:一类事物有多种形态,是一种使用对象的方式,子类重写父类的方法,调用不同的子类对象的相同父类的方法,可以产生不同的效果。

举例:以王者荣耀选英雄为例,英雄类(Hero)为父类,该父类中有一个方法叫 stroke (技能);程咬金和后裔分别为两个子类,两个子类中也有 stroke 这个方法;调用者为另一个父类,有一个选择英雄的方法,该方法需要调用 stroke 这个类方法,最后调用不同的子类(程咬金或后裔)对象,得到不同的技能描述。

#定义父类Hero
class Hero :
    def stroke(self):   #技能函数
        print("英雄技能")

#定义子类程咬金
class ChengYaoJin(Hero):
    def stroke(self):   #技能函数
        print("一技能跳跃,二技能旋转,大招回血")

#定义子类后裔
class HouYi(Hero):
    def stroke(self):   #技能函数
        print("一技能多发,二技能射圈,大招大鸟眩晕")

#定义调用者
class Person:
    def chose_hero(self,hero):  #玩家选择英雄
        hero.stroke()

c = ChengYaoJin()   #程咬金
x = HouYi()     #后裔
p = Person()    #玩家
p.chose_hero(c)     #玩家选择程咬金,"c"换成"x"就会产生不同的结果

执行结果为:
一技能跳跃,二技能旋转,大招回血

多态性:向不同的对象发送不同的信息,不同的对象接收到信息后,会做出不同的反应。

#定义鸟类
class Bird:
    def fly(self):
        print("鸟会飞")

#定义飞机类
class Plane:
    def fly(self):
        print("飞机会飞")

#定义火箭类
class Rocket:
    def fly(self):
        print("火箭会飞")

#函数调用父类的fly方法
def fun1(obj):
    obj.fly()

fun1(Bird())    #调用鸟类的fly方法
fun1(Plane())   #调用飞机类的fly方法
fun1(Rocket())  #调用火箭类的fly方法

执行结果为:
鸟会飞
飞机会飞
火箭会飞
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值