文章目录
本文是我在学习Python过程当中的心得和学习笔记,包含了Python的入门知识,控制结构,列表,字典,元组,集合,字符串,函数等等Python基础内容,并附上了学习的代码,仅供大家参考。如果有问题,有错误欢迎大家留言。剩余的内容可以通过 这篇文章找到。
一、面向对象编程
Python当中一切皆为对象,Python是面向对象的编程语言。
类一般指数据类型,不同的数据类型属于不同的类,例如int类,float类等等。对象一般指类具体化之后的事物,例如100,99,520都是int类之下包含的相似的不同个例,这些个例专业术语成为实例或者对象。
类的组成:类属性、实例方法、静态方法、类方法。
类属性:类中方法以外的变量成为类属性,被该类所有对象所共享。
实例方法:在类当中定义的普通函数,在类外面定义的称为函数,在类内部定义的称为类的方法。
类方法:使用@classmethod修饰的方法, 使用类名直接访问的方法。
静态方法:使用@staticmethod修饰的方法,使用类名直接访问的方法。
1.1类的定义和调用
#类名由一个或多个单词组成,每个单词的首字母大写,其余字母小写
class Student: #Student为类的名称
native_place = '福建' #直接写在类里面的变量,称为类的属性
def __init__(self,name,age): #这是一个实例方法,初始化函数,默认输入的值到这个函数进行操作
self.name = name #self.name 称为实体属性,进行了一个赋值操作,将局部变量的name的值赋值给实体属性
self.age = age
#实例方法
def eat(self): #默认里面加self
print('学生正在吃饭...')
#静态方法
@staticmethod
def method(): #默认里面什么都不加
print('我使用了staticmethod进行修饰,所以我是静态方法')
#类方法
@classmethod
def cm(cls): #默认里面要加cls
print('我是类方法,因为我使用了classmethod进行修饰')
#在类之外定义的称为函数,在类之内定义的称为方法
def drink():
print('喝水')
#创建Student类的对象
stu1 = Student('张三',23) #这里的默认调用初始化函数,两个参数默认输入到这个函数中进行操作
stu1.eat() #调用类的方法,对象名.方法名()
print(stu1.name) #调用类的属性
print(stu1.age)
Student.eat(stu1) #这行代码与stu1.eat()功能相同,都是调用Student类中的eat方法
#类名.方法名(类的对象)-->实际上就是调用方法定义处的self
print(stu1.native_place)
Student.native_place = '北京' #改变类的属性
print(stu1.native_place)
print('-------类方法的使用方式--------')
Student.cm()
print('-------静态方法的使用方式--------')
Student.method()
#动态绑定类的属性和方法
stu2 = Student('李四',30)
print(id(stu1))
print(id(stu2))
stu1.gender = '女'
print(stu1.name, stu1.age, stu1.gender)
print(id(stu1)) #绑定属性前后stu1的ID(内存地址)不变
#print(stu2.name, stu2.age, stu2.gender) #报错,因为stu2没有绑定gender属性
def show():
print('定义在类之外的,称为函数')
stu1.show = show
stu1.show()
#stu2.show() #报错,因为stu2没有绑定show方法
1.2 封装和多态
封装
class Student:
def __init__(self,name,age):
self.name = name
self.__age = age #年龄不希望在类的外部被使用,所以加了__
def show(self):
print(self.name,self.__age)
stu = Student('张三',20)
print(stu.name) #在类的外部使用name,可以访问
#print(stu.__age) #在类的外部使用__age,不能访问,报错
stu.show() #使用类的内置方法去调用,属于内部访问,可以访问
#强行访问__age的方法
print(dir(stu)) #打印出类的全体属性
print(stu._Student__age) #在类的外部可以使用__age
1.3 继承和方法重写
以下图为例老虎、猴子等为子类;哺乳动物为父类;动物为祖先类。
语法格式为:
class 子类类名(父类类名1,父类类名2...):
pass
需要注意的是:
1.Python支持多继承(属于Python特色了),即一个子类可以继承多个父类。
class A(object):#A类继承object
pass
class B(object):#B类继承object
pass
class C(A,B):#C类继承A, B
pass
2.定义子类时,必须在其构造函数当中调用其父类的构造函数。
方法重写:父类的方法在子类当中重新编写(即更改的意思)
3.如果一个类没有继承任何类,那么默认继承object类。使用内置函数dir( )可以察看指定对象的所有属性和方法。
class Student:
def __init__(self,name,age):
self.name = name
self.age = age
def __str__(self):
return '我的名字是{0},今年{1}岁'.format(self.name,self.age)
#字符串格式化输出
stu = Student('张三',20)
print(dir(stu)) #输出类的所有属性和方法
print(stu) #若不在Student中重写__str__()方法,则输出的是Student类的地址
#这里我们重写了,则输出的是return中的语句
class Person(object): #Person继承object,object也可以不写
def __init__(self,name,age):
self.name = name
self.age = age
def info(self):
print(self.name,self.age,end='\t')
class Student(Person): #Student继承Person类
def __init__(self, name, age,stu_no):
# 先初始化父类属性,然后在对子类的属性进行幅值,super().可以理解为调用了父类的方法
# super().是为了解决多继承当中多个父类的问题,倘若父类当中的方法名称相同,则可以在super().当中说明调用的是哪个父类的方法
super().__init__(name,age)
self.stu_no = stu_no
def info(self): #方法重写
super().info()
print('学号:{0}'.format(self.stu_no))
class Teacher(Person): #Teacher继承Person类
def __init__(self, name, age,teach_of_year):
super().__init__(name,age)
self.teach_of_year = teach_of_year
#创建实例对象
stu = Student('张三',20,'1001')
teacher = Teacher('李四',34,10)
#调用父类的方法
stu.info()
teacher.info()
1.4 多态
Java是静态语言,Python是动态语言
class Animal(object):
def eat(self):
print('动物会吃')
class Dog(Animal):
def eat(self):
print('狗吃骨头...')
class Cat(Animal):
def eat(self):
print('猫吃鱼...')
class Person:
def eat(self):
print('人吃五谷杂粮')
#定义一个函数,这里就使用了多态
#先判定obj的类型,然后在根据其类型调用其方法
def fun(obj):
obj.eat()
#调用函数
cat1 = Cat()
cat1.eat()
print('----------------')
fun(Cat())
fun(Dog())
fun(Animal())
fun(Person())
'''Dog和Cat是重写了父类当中的方法,Person虽然和Animal没有继承关系
但是通过多态,我们可以利用一个函数就将他们的输出联系起来
在Python当中,我们只关注对象的行为(方法)是否类似,而不关注对象类型是否相同'''
1.5 特殊属性和特殊方法
#特殊属性__dict__
class A:
pass
class B:
pass
class C(A,B):
def __init__(self,name,age):
self.name = name
self.age = age
#创建C类的对象
x = C('Jack',20) #x是C类的一个实例对象
print(x.__dict__) #实例对象的属性字典
print(C.__dict__) #C类的属性字典
print(x.__class__) #<class '__main__.C'>,,表明属于C类
print(C.__bases__) #C类的父类类型元素
print(C.__base__) #输出C类的父类,AB谁写前面就输出谁,这里是A
print(C.__mro__) #C类的层次结构,即输出所有父类和祖先类(包括object)
print(A.__subclasses__()) #输出A的所有子类,仅C类一个
#特殊方法
class Student:
def __init__(self,name):
self.name = name
def __add__(self,other): #实现两个对象相加
return self.name+other.name
def __len__(self):
return len(self.name)
stu1 = Student('Jack')
stu2 = Student('李四')
s = stu1+stu2
print(s) #报错,显示不能相加
#倘若非得相加,那么在Student类当中定义__add__函数
s2 = stu1.__add__(stu2) #和前面的功能相同,实现相加操作
print(s2)
lst = [11,22,33,44]
print(len(lst)) #输出列表长度
print(lst.__len__())
print(len(stu1))
'''总结:执行实例创建:
1.先将类名(Person)传给new的cls,开新空间(obj)用于后续实例对象创建
2.接受到obj的self,实例对象p1指向self
3.new在前为实例创建对象,init为实例的属性赋值,因此在我们创建一个实例对象(如p1)时,首先调用的是new创建,然后在调用init赋值
(可以使用debug逐步观察)
'''
class Person(object):
def __new__(cls,*args,**kwargs): #传入参数为Person类对象(观察id可以看出)
print('__new__被调用了,cls的id值为{0}'.format(id(cls)))
obj = super().__new__(cls)
print('创建的对象的id为:{0}'.format(id(obj)))
return obj
def __init__(self,name,age): #传入参数为实例对象p1,self=p1(观察id可以看出)
print('__init__被调用了,self的id值为:{0}'.format(id(self)))
self.name = name
self.age = age
print('object这个类的对象的id为:{0}'.format(id(object)))
print('Person这个类的对象的id为:{0}'.format(id(Person)))
#创建Person类的实例对象
p1 = Person('张三',20)
print('p1这个Person类的实例对象的id:{0}'.format(id(p1)))
1.6 拷贝
class CPU:
pass
class Disk:
pass
class Computer:
def __init__(self,cpu,disk):
self.cpu = cpu
self.disk = disk
#变量赋值
cpu1 = CPU()
cpu2 = cpu1
print(cpu1,id(cpu1))
print(cpu2,id(cpu2)) #cpu1和cpu2 id相同,体现了Python赋值的驻留机制,即虽然形成两个变量,但是实际上还是指向同一个对象
#浅拷贝
import copy
disk = Disk() #创建一个硬盘类对象
computer = Computer(cpu1,disk)
computer2 = copy.copy(computer)
print(computer,computer.cpu,computer.disk)
print(computer2,computer2.cpu,computer2.disk)
print('----------------------------------')
#深拷贝
computer3 = copy.deepcopy(computer)
print(computer,computer.cpu,computer.disk)
print(computer3,computer3.cpu,computer3.disk)
'''
总结:
computer和computer2的cpu disk id相同,但是本身的id不同,这就称为浅拷贝
浅拷贝后对象的属性(这里是id变化了)改变,但子对象(被调用的类)不变(这里是cpu和disk)。
深拷贝是对象的属性和子对象全部发生改变,所有属性和子对象的id改变
'''
二、 模块化编程
一个模块当中可以包含多个函数、类、语句。在Python当中一个.py文件就是一个模块。
使用模块的好处有:
方便其它程序和脚本的导入并使用;
避免函数名和变量名冲突;
提高代码的可维护性;
提高代码的可重用性。
2.1 模块调用
导入模块的两种方法
import math #关于数学运算的模块,可以使用模块中的所有函数、类
print(id(math))
print(type(math))
print(math)
print(math.pi)
print('----------------------')
print(dir(math))
print(math.pow(2,3))
from math import pi #仅仅导入一个特定的对象
print(pi)
#print(math.pow(2,3)) #报错
定义自定义模块calc.py
#自定义模块calc.py
def add(a,b):
return a+b
调用自定义模块calc.py
import calc
print(calc.add(10,20))
在主程序当中调用
#自定义模块calc.py
def add(a,b):
return a+b
if __name__ == '__main__':
print(add(10,20))
'''只有执行calc.py文件时,才会输出这个语句'''
2.2 Python中的包
包类似于C语言当中的多个头文件组成的头文件,其中调用了多个模块。为了避免名称相同的模块冲突,而设置的包。
#导入package1包中的module_A模块
import package1.module_A
print(package1.module_A.a)
'''
import package1.module_A as ma #ma是package1.module_A的别名
print(ma.a)
#二者作用相同
'''
#导入带有包的模块时的注意事项
import package1
import calc
#使用import方式进行导入时,只能跟包名或者模块名
from package1 import module_A
from package1.module_A import a
#使用from ...import可以导入包、模块、函数、变量等等
2.3 Python当中常用的模块
shcedule模块需要下载,在pycharm中左下角点击小正方形,然后再点击packages,最后在搜索框中搜索schedule,下载即可。
import schedule
import time
def job():
print('哈哈 --------')
schedule.every(3).seconds.do(job)
#每3秒执行一次job()
while True:
schedule.run_pending()
time.sleep(1) #休眠1秒
2.4 文件读写
file = open('a.txt','r',encoding='UTF-8')
print(file.readlines())
file.close()
with语句(上下文管理器),with语句可以自动管理上下文资源,不论什么原因跳出with块,都能确保文件正确的关闭,以此来达到释放资源的目的。
如下代码所示,使用with语句打开文件,就不再需要 file.close( )。
with open('a.txt','r',encoding='UTF-8') as file:
print(file.read())
2.5 OS模块的常见函数
os模块是Python内置的与操作系统功能和文件系统相关的模块,该模块中的语句的执行结果通常与操作系统有关,在不同的操作系统上运行,得到的结果可能不一样。
os模块与os.path模块用于对目录或文件进行操作。
#os模块是与操作系统相关的一个模块
import os
os.system('notepad.exe') #打开记事本
os.system('calc.exe') #打开计算器
#直接调用可执行文件(.exe文件)
os.startfile('D:\\QQ\\Bin\\QQScLauncher.exe')
# os.startfile('D:/QQ/Bin/QQScLauncher.exe') # 相同
#打开QQ
import os
print(os.getcwd())
lst = os.listdir('../chap12')
print(lst)
#os.mkdir('newdir2')
#os.makedirs('A/B/C')
#os.rmdir('newdir2')
#os.removedirs('A/B/C')
import os.path
print(os.path.abspath('demo12.py'))
print(os.path.exists('demo12.py'),os.path.exists('demo18.py')) #判断文件是否存在
print(os.path.join('E:\\python','demo12.py')) #仅仅是单纯的拼接,文件没有复制,没有其他操作
print(os.path.split('D:\\software\\pycharm\\project\\hi\\chap12\\demo12.py')) #将文件名和路径名分开
print(os.path.splitext('demo12.py')) #将文件名和后缀名分开
print(os.path.basename('D:\\software\\pycharm\\project\\hi\\chap12\\demo12.py')) #从路径当中将文件名+后缀名提取出来