学霸:计划失败 -> 沮丧 -> 骂自己一顿 -> 深度思考计划为啥失败 -> 改善问题 -> 制订新计划
学习思维:案例学习
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
' a test module '
__author__ = '黯雅'
#第1行注释可以让这个hello.py文件直接在Unix/Linux/Mac上运行,第2行注释表示.py文件本身使用标准UTF-8编码
#sys模块有一个argv变量,用list存储了命令行的所有参数。argv至少有一个元素,因为第一个参数永远是该.py文件的名称
#运行python3 hello.py获得的sys.argv就是['hello.py']
import sys
def test():
args = sys.argv
if len(args)==1:
print('Hello, world!')
elif len(args)==2:
print('Hello, %s!' % args[1])
else:
print('Too many arguments!')
if __name__=='__main__':
test()
#作用域
#正常的函数和变量名是公开的(public),可以被直接引用比如:abc,x123,PI等
#类似__xxx__这样的变量是特殊变量,可以被直接引用,但是有特殊用途,比如上面的__author__,__name__就是特殊变量,自己的变量一般不要用这种变量名
#_xxx和__xxx这样的函数或变量就是非公开的(private)
#private函数和变量“不应该”被直接引用,而不是“不能”被直接引用,Python并没有一种方法可以完全限制访问private函数或变量
def _private_1(name):
return 'Hello, %s' % name
def _private_2(name):
return 'Hi, %s' % name
def greeting(name):
if len(name) > 3:
return _private_1(name)
else:
return _private_2(name)
print(greeting('黯雅'))
#安装第三方模块
#在Python中,安装第三方模块,是通过包管理工具pip完成的
#第三方库都会在Python官方的pypi.python.org网站注册,要安装一个第三方库,必须先知道该库的名称,可以在官网或者pypi上搜索,比如Pillow的名称叫Pillow
#安装命令 pip install Pillow 等待安装完成
#有了Pillow,处理图片易如反掌
#>>> from PIL import Image
#>>> im = Image.open('test.png')
#>>> print(im.format, im.size, im.mode)
#PNG (400, 300) RGB
#>>> im.thumbnail((200, 100))
#>>> im.save('thumb.jpg', 'JPEG')
import sys
print(sys.path)
#面向对象过程
#定义一个特殊的__init__方法,在创建实例的时候,就把name,score等属性绑上去
#self,表示创建的实例本身
#让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,外部代码要获取修改name和score就getSet方法啊
#object 父类
class Student(object):
def __init__(self,name,score):
self._name=name
self._score=score
def print_student(self):
print('%s: %s' % (self._name, self._score))
print('Message:',self._name,self._score)
def get_grade(self):
if self._score >= 20:
return 'A'
elif self._score >= 40:
return 'B'
else:
return 'C'
input_mes1 = Student('黯雅',13)
input_mes2 = Student('黯雅',45)
input_mes1.print_student();
print(input_mes1.get_grade())
input_mes2.print_student();
print(input_mes2.get_grade())
#不能直接访问__name是因为Python解释器对外把__name变量改成了_Student__name,所以,仍然可以通过_Student__name来访问__name变量:
#强烈建议你不要这么干,因为不同版本的Python解释器可能会把__name改成不同的变量名
#print(input_mes1._Student__name)
#print(input_mes2._Student__name)
#判断一个变量是否是某个类型可以用isinstance()判断
print(isinstance(input_mes1, Student))
#参数也可传递
def run_twice(animal):
animal.print_student()
animal = Student('AAA',34)
run_twice(animal)
#--获取对象---type()
#当我们拿到一个对象的引用时,如何知道这个对象是什么类型、有哪些方法呢?
print(type(Student))
print(type(input_mes1))
print(type(123)==type(456))
print(type(123)==int)
print(type('abc')==str)
#判断是否是函数
import types
def fn():
pass
print('FunctionType ',type(fn)==types.FunctionType)
print('BuiltinFunctionType ',type(abs)==types.BuiltinFunctionType)
print('LambdaType ',type(lambda x: x)==types.LambdaType)
print('GeneratorType ',type((x for x in range(10)))==types.GeneratorType)
#使用isinstance()判断class类型
#isinstance()判断的是一个对象是否是该类型本身,或者位于该类型的父继承链上
print('isinstance ',isinstance(1234, int))
print('isinstance ',isinstance('abc', str))
print('isinstance ',isinstance(input_mes1, Student))
print('多个类型中判断',isinstance([1, 2, 3], (list, tuple)))
#获得一个对象的所有属性和方法
print('获得一个对象的所有属性和方法:',dir(input_mes1))
#在len()函数内部,它自动去调用该对象的__len__()方法,所以是等价的
#print('长度: ',len('ABC'),'ABC'._len_(), 'ABC'.lower())
#配合getattr()、setattr()以及hasattr(),我们可以直接操作一个对象的状态
class MyObject(object):
def __init__(self):
self.x = 9
def power(self):
return self.x * self.x
print(hasattr(MyObject(),'x'))
setattr(MyObject(), 'y', 19) # 设置一个属性'y'
print(hasattr(MyObject(),'y'))
print(getattr(MyObject(),'x'))
#--实例属性和类属性---
#接在class中定义属性,这种属性是类属性
class Teacher(object):
name='Teacher' #类属性
t = Teacher()
print('打印类属性:',Teacher.name)
t.name='Teacher1' #由于实例属性优先级比类属性高,因此,它会屏蔽掉类的name属性
print('打印实例属性',t.name)
#面向对象高级编程
#数据封装、继承和多态只是面向对象程序设计中最基础的3个概念,面向对象还有很多高级特性:如多重继承、定制类、元类等概念
#创建了一个class的实例后,我们可以给该实例绑定任何属性和方法,这就是动态语言的灵活性
class Student1(object):
pass
#给实例绑定一个属性:
s2 = Student1();
s2.name = 'Macal'
print('绑定一个属性',s2.name)
#给实例绑定一个方法:
def set_age(self,age): # 定义一个函数作为实例方法
self.age = age
from types import MethodType
s2.set_age = MethodType(set_age, s2)#对类实例进行绑定
s2.set_age(20)
print('实例类进行绑定方法',s2.age)
s3 = Student1() #从新建立实例调用,就会报错
#s3.set_age(21)
#对类进行绑定
def set_score(self, score):
self.score = score
Student1.set_score = set_score #直接对类进行绑定
s3.set_score(23)
print('直接对类进行绑定方法:',s3.score)
#定义一个特殊的__slots__变量,来限制该class实例能添加的属性:
class Student3(object):
__slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
s3 = Student3()
s3.name = "MAC"
s3.age = 21
#s3.score =28 报错
print('__slots__变量:',s3.name,s3.age)
#使用@property
#和java一样get set 方法
class Student4(object):
def set_score(self,value):
if not isinstance(value, int):
raise ValueError('score must be an integer!')
if value < 0 or value > 100:
raise ValueError('score must between 0 ~ 100!')
self._score =value
def get_score(self):
return self._score
a = Student4()
a.set_score(12)
print('get set 方法:',a.get_score())
#Python内置的@property装饰器就是负责把一个方法变成属性调用的:
class Student5(object):
@property
def score(self):
return self._score
@score.setter
def score(self, value):
if not isinstance(value, int):
raise ValueError('score must be an integer!')
if value < 0 or value > 100:
raise ValueError('score must between 0 ~ 100!')
self._score = value
s4 = Student5()
s4.score = 40
print('使用property属性:',s4.score)
#练习
#请利用@property给一个Screen对象加上width和height属性,以及一个只读属性resolution:
class Screen(object):
@property
def width(self):
return self._width
@property
def height(self):
return self._height
@width.setter
def width(self,value):
if value < 0 or value > 100:
raise ValueError('width must between 0 ~ 100!')
self._width=value
@height.setter
def height(self,value):
if value < 0 or value > 100:
raise ValueError('height must between 0 ~ 100!')
self._height=value
@property
def resolution(self):
return 'width:%s,hight:%s,resolution:%s' % (self._width,self._height,self._width*self._height)
f = Screen()
f.height=20
f.width=20
print(f.resolution)
案例2
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#多继承 (java中一个类只能继承一个父类,但是在python中可以继承多个父类,这就是唯一区别)
#1-0
class animal(object):
pass
#1-1
class Runable(object):
def run(self):
print('Running.....')
class Flying(object):
def fly(self):
print('Flying.......')
#2 多继承
class Mammal(animal,Runable):
pass
class Bird(animal,Flying):
pass
#3
class Dog(Mammal):
pass
class Bat(Mammal):
pass
class Parrot(Bird):
pass
class Ostrich(Bird):
pass
#---定制类----
class Student(object):
def __init__(self,name):
self._name = name
def __str__(self):
return '定制类return values: %s'%self._name
__repr__ = __str__
s = Student('请 你')
s
print(Student('请 你'))
#----__iter__------
#一个类想被用于for ... in循环,类似list或tuple那样,就必须实现一个__iter__()方法,该方法返回一个迭代对象
#像list那样按照下标取出元素,需要实现__getitem__()方法
#计算斐波那契数列
class Fib(object):
def __init__(self):
self.a,self.b = 0,1
def __iter__(self):
return self #实例本身就是迭代对象,故返回自己
def __next__(self):
self.a ,self.b = self.b,self.a+self.b
if self.a>10000:
raise StopIteration()
return self.a
def __getitem__(self, item):
if isinstance(item, int): # n是索引
a, b = 1, 1
for x in range(item):
a, b = b, a + b
return a
if isinstance(item, slice): # n是切片
start = item.start
stop = item.stop
if start is None:
start = 0
#if stop is None:这里不允许后切片为空的情况。因为是一个一个计算的
a, b = 1, 1
L = []
for x in range(stop):
if x >= start:
L.append(a)
a, b = b, a + b
return L
for x in Fib():
print('函数迭代的值:',x)
print('得到函数下标未4的值:',Fib()[4])
print('函数切片:',Fib()[:15])
print('普通切片:',list(range(11))[2:10])
#----__getattr__---
#当我们调用类的方法或属性时,如果不存在,就会报错,
#当调用不存在的属性时,比如score,Python解释器会试图调用__getattr__(self, 'score')来尝试获得属性,重写这个方法
class Fib1(object):
def __init__(self,name):
self._name_ = name
def __getattr__(self, item):
if item == 'score':
return 90
s= Fib1('Macal')
print('调用存在的属性:',s._name_)
print('调用不存在的属性:',s.score)
#---_call()---
#一个对象实例可以有自己的属性和方法
class Student(object):
def __init__(self, name):
self.name = name
def __call__(self):
print('My name is %s.' % self.name)
s = Student('Milll')
s()
#---使用枚举类---
from enum import Enum
Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))
for name, member in Month.__members__.items():
print(name, '=>', member, ',', member.value)
from enum import Enum, unique
@unique
class Weekday(Enum):
Sun = 0 # Sun的value被设定为0
Mon = 1
Tue = 2
Wed = 3
Thu = 4
Fri = 5
Sat = 6
day1 = Weekday.Sun
print(day1)
print(Weekday['Tue'])
print(Weekday['Tue'].value)
print(day1 == Weekday.Sun)
print(Weekday(1))
for name, member in Weekday.__members__.items():
print(name, '=>', member,member.value)
#!/usr/bin/senv python3
# -*- coding: utf-8 -*-
import os
print(os.name)
print(os.environ)
print(os.environ.get('PATH'))
#查看当前目录的绝对路径:
print(os.path.abspath('.'))
# 在某个目录下创建一个新目录
os.path.join(os.path.abspath('.'),'tnt')
# 然后创建一个目录:
os.makedirs(os.path.abspath('.')+'/tnt')
# 删掉一个目录:
os.rmdir(os.path.abspath('.')+'/tnt')
#通过os.path.split()函数,这样可以把一个路径拆分为两部分,后一部分总是最后级别的目录或文件名
print(os.path.split(os.path.abspath('.')))
#直接让你得到文件扩展名
print(os.path.splitext('.'))
# 对文件重命名:
#os.rename('test.txt', 'test.py')
# 删掉文件:
#os.remove('test.py')
#列出当前目录下的所有目录
print([x for x in os.listdir('.') if os.path.isdir(x)])
#要列出所有的.py文件
print( [x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1]=='.py'])
#----序列化---
#变量从内存中变成可存储或传输的过程称之为序列化(python)
#网络和本地存储在过程中的转化成为序列化(Java)
import pickle
d =dict(name='黯雅',scor=98,age=20)
print(pickle.dumps(d))#pickle.dumps()方法把任意对象序列化成一个bytes
#就可以把这个bytes写入文件。或者用另一个方法pickle.dump()直接把对象序列化后写入一个file-like Object
f = open('1.txt','wb')
pickle.dump(d,f)
f.close()
f = open('1.txt','rb')
d = pickle.load(f)
f.close()
print('pickle序列化:',d)
#注意:它只能用于Python,并且可能不同版本的Python彼此都不兼容,因此,只能用Pickle保存那些不重要的数据,不能成功地反序列化也没关系
#Python的dict对象可以直接序列化为JSON的{}
import json
class Student(object):
def __init__(self,name,age,score):
self.name = name
self.score = score
self.age = age
def student2dict(st):
return {
'name':st.name,
'age':st.age,
'score':st.score
}
s= Student('anya',23,22)
print('json序列化:',json.dumps(s,default=student2dict))
#反序列化 (报错)
def dict2student(st):
return Student(st['name'],st['age'],st['score'])
json_str={"name":"anya", "age":25, "score":28}
print('json反序列化:',json.loads(json_str,object_hook=dict2student))
如果有兴趣的童鞋,可以加群交流交流: