第七课:面向对象(下)、异常处理、包和模块

# 概述:
上一节主要介绍了面向对象的一些基本概念:类,类的组成元素“方法和属性”,类的特性“继承,多态和封装”。这一节课分为三部分:
(一)类属性、类方法及调用、静态方法及调用和单例类
(二)异常处理
(三)包和模块

# 第一部分:类方法、静态方法和单例类
**类属性**
(1)类属性区别于实例的属性,类属性属于类对象,被实例对象所共享
(2)查找属性规则:先实例对象的实例属性;后类对象的类(?)属性
(3)通过实例对象不能修改类属性的值;如果修改的属性在实例中不存在,则动态添加实例属性
```
class Person:
sum_num = 0

def __init__(self):
Person.sum_num += 1 #修改类属性值,每创建一个实例对象,类属性值加1

#实例对象p1和类对象的类属性值一致
p1 = Person("zhangsan")
print(p1.sum_num, Person.sum_num)


#通过实例对象不能修改类属性值,如果修改的属性在实例总不存在,则动态添加实例属性
p1.sum_num = 100
print(p1.sum_num, Person.sum_num)


```
**类方法及调用**

(1)使用@classmethod修饰的方法,第一个参数是cls
(2)类方法操作类属性;实例方法操作实例对象属性
(3)调用方式:类名.类方法();实例对象.类方法() #不推荐用此方法调用类方法
```
class Date(object):

def __init__(self, day=0, month=0, year=0):
self.day = day
self.month = month
self.year = year

#类方法
@classmethod
def from_string(cls, date_as_string):
day, month, year = map(int, date_as_string.split('-'))
date1 = cls(day, month, year)
return date1
```
**静态方法及调用**

(1)使用@staticmethod修饰的方法,不需要传入任何参数
(2)应用在跟类和对象没有关系的一些功能上。尽量少用静态方法。
```
#静态方法
@staticmethod
def is_date_valid(date_as_string):
day, month, year = map(int, date_as_string.split('-'))
return day <= 31 and month <= 12 and year <= 3999
```
**单例类**
(1)__new__(cls)是超类object类内置的方法。参数cls是类对象
(2)用户创建对象,返回创建对象的引用。
```
#通过id(cls)可以查看类对象以及实例对象的地址
class DataBaseObj(object):
def __init__(self): #对象初始化
print("-------init 构造函数-------")

def __new__(cls): #构造对象
print("cls_id:" id(cls))
return object.__new__(cls) #返回对象的引用
```
(3)在整个程序系统中,只有一个实例对象。概念等同设计模式中的singleton模式。
```
class SingleInstance:
__instance = None
def __init__(self):
print("-----init-----")

def __new__(cls):
if cls.__instance == None:
cls.__instance = object.__new__(cls)
return cls.__instance

s1 = SingleInstance()
print(id(s1))
s2 = SingleInstance()
print(id(s2))
```

# 第二部分:异常处理
(1)捕获异常
```
try:
逻辑代码
except ExceptionType as err:
异常处理
```
(2)捕获多个异常
```
try:
逻辑代码
except (ExceptionType1, ExceptionType2, ...) as err:
异常处理
```
(3)捕获所有可能发生的异常
```
try:
逻辑代码
except Exception as err:
异常处理
```
(4)finally
```
try:
逻辑代码
except Exception as err:
异常处理
finally:
代码块 (无论是否有异常发生,代码都会执行到这里)
```
(4)异常处理的意义:
* 防止某个业务产生异常而影响到整个程序中的其他业务
* 异常处理的本质不是解决异常,而是将出现异常时的不良影响降到最低

# 第三部分:包和模块
**(一)Python项目结构:**
(1)1个项目:n个包
(2)一个包:n个模块
(3)模块的名字:以.py为扩展名命名的文件
**(二)引入模块的方法:**
(1)导入一个模块:import model_name 或者 import module_name.model_name
(2)导入多个模块:import model_name1, model_name2, ...
(3)导入某个模块中的函数:from model_name import fun1, fun2
**(三)import model_name Vs from model_name import fun**
(1)前者是导入一模块,如果想引用模块的内容(class, method,variables...)必须用全名,即 [module_name].[attr_name]。
(2)后者是导入某一指定对象(class, 其它对象...), 然后就可以直接用这些对象,不需要加上[module_name], 即[attr_name]。
**(四)特别用法:**
(1)如果你只想导入一个包里面的某个模块被其他包所使用,你可以在__init__.py文件里添加一句:__all__ = ["model_name"]
(2)批量导入:from package import *;(1)对(2)起约束作用。
继续阅读 »
# 概述:
上一节主要介绍了面向对象的一些基本概念:类,类的组成元素“方法和属性”,类的特性“继承,多态和封装”。这一节课分为三部分:
(一)类属性、类方法及调用、静态方法及调用和单例类
(二)异常处理
(三)包和模块

# 第一部分:类方法、静态方法和单例类
**类属性**
(1)类属性区别于实例的属性,类属性属于类对象,被实例对象所共享
(2)查找属性规则:先实例对象的实例属性;后类对象的类(?)属性
(3)通过实例对象不能修改类属性的值;如果修改的属性在实例中不存在,则动态添加实例属性
```
class Person:
sum_num = 0

def __init__(self):
Person.sum_num += 1 #修改类属性值,每创建一个实例对象,类属性值加1

#实例对象p1和类对象的类属性值一致
p1 = Person("zhangsan")
print(p1.sum_num, Person.sum_num)


#通过实例对象不能修改类属性值,如果修改的属性在实例总不存在,则动态添加实例属性
p1.sum_num = 100
print(p1.sum_num, Person.sum_num)


```
**类方法及调用**

(1)使用@classmethod修饰的方法,第一个参数是cls
(2)类方法操作类属性;实例方法操作实例对象属性
(3)调用方式:类名.类方法();实例对象.类方法() #不推荐用此方法调用类方法
```
class Date(object):

def __init__(self, day=0, month=0, year=0):
self.day = day
self.month = month
self.year = year

#类方法
@classmethod
def from_string(cls, date_as_string):
day, month, year = map(int, date_as_string.split('-'))
date1 = cls(day, month, year)
return date1
```
**静态方法及调用**

(1)使用@staticmethod修饰的方法,不需要传入任何参数
(2)应用在跟类和对象没有关系的一些功能上。尽量少用静态方法。
```
#静态方法
@staticmethod
def is_date_valid(date_as_string):
day, month, year = map(int, date_as_string.split('-'))
return day <= 31 and month <= 12 and year <= 3999
```
**单例类**
(1)__new__(cls)是超类object类内置的方法。参数cls是类对象
(2)用户创建对象,返回创建对象的引用。
```
#通过id(cls)可以查看类对象以及实例对象的地址
class DataBaseObj(object):
def __init__(self): #对象初始化
print("-------init 构造函数-------")

def __new__(cls): #构造对象
print("cls_id:" id(cls))
return object.__new__(cls) #返回对象的引用
```
(3)在整个程序系统中,只有一个实例对象。概念等同设计模式中的singleton模式。
```
class SingleInstance:
__instance = None
def __init__(self):
print("-----init-----")

def __new__(cls):
if cls.__instance == None:
cls.__instance = object.__new__(cls)
return cls.__instance

s1 = SingleInstance()
print(id(s1))
s2 = SingleInstance()
print(id(s2))
```

# 第二部分:异常处理
(1)捕获异常
```
try:
逻辑代码
except ExceptionType as err:
异常处理
```
(2)捕获多个异常
```
try:
逻辑代码
except (ExceptionType1, ExceptionType2, ...) as err:
异常处理
```
(3)捕获所有可能发生的异常
```
try:
逻辑代码
except Exception as err:
异常处理
```
(4)finally
```
try:
逻辑代码
except Exception as err:
异常处理
finally:
代码块 (无论是否有异常发生,代码都会执行到这里)
```
(4)异常处理的意义:
* 防止某个业务产生异常而影响到整个程序中的其他业务
* 异常处理的本质不是解决异常,而是将出现异常时的不良影响降到最低

# 第三部分:包和模块
**(一)Python项目结构:**
(1)1个项目:n个包
(2)一个包:n个模块
(3)模块的名字:以.py为扩展名命名的文件
**(二)引入模块的方法:**
(1)导入一个模块:import model_name 或者 import module_name.model_name
(2)导入多个模块:import model_name1, model_name2, ...
(3)导入某个模块中的函数:from model_name import fun1, fun2
**(三)import model_name Vs from model_name import fun**
(1)前者是导入一模块,如果想引用模块的内容(class, method,variables...)必须用全名,即 [module_name].[attr_name]。
(2)后者是导入某一指定对象(class, 其它对象...), 然后就可以直接用这些对象,不需要加上[module_name], 即[attr_name]。
**(四)特别用法:**
(1)如果你只想导入一个包里面的某个模块被其他包所使用,你可以在__init__.py文件里添加一句:__all__ = ["model_name"]
(2)批量导入:from package import *;(1)对(2)起约束作用。
收起阅读 »

第一课 爬虫的基础技术

一、HTTP协议及HTML相关技术
(一)、HTTP协议

image.png


1.png


2.png



 
(二)、HTTP HEADER


image.png


红色标记比较重要
Keep-Alive功能使客户端到服务器的连接持续有效,当出现对后继请求时, Keep-Alive功能避免了建立或者重新建立连接。
HTTP/1.1默认所有情况下在HTTP1.1中所有连接都被保持,除非在请求头或响应头中指明要关闭:Connection:Close

image.png


(三)、HTTP请求方法

image.png


(四)、HTTP响应状态码
1、2XX  成功
2、3XX  跳转
3、4XX  客户端错误
4、5XX  服务器错误
 
300
1、300 Multiple Choices 存在多个可用的资源,处理或丢弃
2、301 Moved Permanetly重定向
3、302 Found 重定向
4、304 Not Modified 请求的资源未更新,丢弃
一些 Python 库,例如urllib2已结对重定向做了处理,会自动跳转;动态网页处理的时候也是自动跳转,所以不需要单独处理。
 
400、500
1、400 Bad Request客户端请求有语法错误,不能被服务器所 请求有语法错误,不能被服务器所理解
2、401 Unauthorized请求未经授权,这个状态代码必须和 WWW-Authenticate报头域一起使用
3、403 Forbidden服务器收到请求,但是拒绝提供 服务
4、404 Not Found请求资源不存在, eg :输入了错误的URL
5、 500 Internal Server Error服务器 发生不可预期的错误
6、503 Server Unavailable服务器当前不能处理客户端的请求,一段时间后可能恢复正常
 
错误处理
1、400 Bad Request 检查请求的参数或者路径
2、401 Unauthorized如果需要授权的网页,尝试重新登录
3、403 ForbiddenForbidden Forbidden
(1)如果是需要登录的网站,尝试重新登录
(2)IP 被封,暂停爬取并增加虫的等待时间,如果拨号网络尝试重新联网更改 IP
4、404 Not Found 直接丢弃
6、5XX 服务器错误, 直接丢弃,并计数,如果连续不成功,WARNING并停止爬取
 
(五)、HTML及CSS


image.png


image.png


HTML 超文本标记语言,简单来说可以认为一种规范或者协议浏 览器根据HTML的语言规范来解析
HTML里与爬虫相关的规范有以下:
这一类 tagtag 标记了外链用来做抓取,而 tr 、p用来进行内容抽取
• Tag:<a> <tr > <p >
id 、class 用在 css 上的,能帮助我们定位元素,作用于tr p 类似:
• Class: class=“home -price”
• Id: id=‘price -frame’ 
 
(六)、DOM树


image.png


(七)、Javascript
Javascript就是运行在前端的编程语言,最典型用动态网页数据、内容加载及呈现上, javascript做网络请求的时候最常用技术成为AJAX(Asynchronous JavaScript and XML),专门用来异步请求数据,这些是我们抓取的时候需要用到的。
 
二、宽度及深度抓取
(一)、网页抓取原理

image.png


(二)、爬虫的抓取对象类型
1、静态网页
2、动态网页
3、Web Service
(三)、深度优先策略


image.png


 
(四)、宽度优先策略


image.png


 
(五)、选择哪种策略
1、重要的网页距离种子站点比较近
2、 万维网的深度并没有很,一个页多路径可以到达 
3、 宽度优先有利于多爬虫并行合作抓取
4、深度限制于宽度优先相结合
 
三、不重复抓取策略
(一)、如何记录抓取历史
1. 将访问过的URL保存到数据库效率太低
2. 用HashSet HashSet 将访问过的 URL 保存起来。那只需接近 O(1)的代价就可以查到一个 URL是否被访问过了。 消耗内存
3. URL 经过 MD5 或SHA -1等单向哈希后再保存到 HashSet 或数据库。
4. Bit-Map方法。建立一个 BitSet ,将每个 URL 经过一个哈希函数映射到某一位。
(二)、MD5函数
MD5 签名是一个哈希函数,可以将任意长度的据量转换为固定长度数字,(通常是 4个整型, 128 位)。计算机不可能有 2的128 那么大内存,因此实际的哈 希表都会是 URL.MD5再%n (即取模)。现实世界的URL组合必然超越哈希表的槽位数,因此碰撞是一定存在的,一般的Hash函数,例如Java的HashTable是一 个HASH 表再跟上一个链表,链表里存的是碰撞的结果。

image.png


(三)、提高效率
1、评估网站的页数量
2、选择合适的 HASH 算法和空间阈值, 降低碰撞几率
3、选择合适的存储结构和算法
(四)、评估网页数量
site:网址
(五)、BITMAP方式记录
将URL的MD5值再次哈希,用一个或多BIT位来记录一个URL :
1. 确定空间大小 e.g.  facebook 1.5Gb
2. 按倍增加槽位 e.g. 16GB
3. HASH算法映射 ( murmurhash3, cityhash)Python: mmh3 bitarray
 
pip install murmurhash3 bitarray


image.png



• 优势:对存储进行了进一步压缩,在 MD5 的基础上,可以从 128 位最多压缩到 1位,一般情况如果用 4bit或者 8bit表示一个 url ,也能压缩 32 或者 16 倍
• 缺陷 :碰撞概率增加
(六)、Bloom Filter 
Bloom Filter使用了多个哈希函数,而不是一个。 创建一个 m位BitSet,先将所有位初始化为 0,然后选择 k个不同的哈希函数。第 i个哈希函数对字符串str哈希的结果记为 h(i,str ),且 h(i,str )的范围是 0到m-1。
只能插入,不能删除!!


image.png


(七)、pybloomfilter
安装
pip install pybloomfilter(可能运行时会 crash crash )
git clone https://github.com/axiak/pybloomfiltermmap.git 
python setup.py install
构造函数
class pybloomfilter.BloomFilter(capacity : int, error_rate:float[,filename=None:String][, perm=0755 ])
并不实际检查容量,如果需要比较低的error_rate,则需要设置更大的容量


image.png



官方文档
https://media.readthedocs.org/pdf/pybloomfiltermmap3/latest/pybloomfiltermmap3.pdf 
 
(八)、如何有效记录抓取历史
1、多数情况下不需要压缩,尤其网页量少的
2、网页数量大的情况下,使用 Bloom Filter压缩
3、重点是计算碰撞概率,并根据来确定存储空间的阈值
4、分布式系统、将散列映射到多台主机的内存
 
四、网站结构分析
1、网站对爬虫的限制
2、利用sitemap来分析网站结构和估算目标网页的规模
3、有效率抓取特定内容
      利用sitemap里的信息,直接对网页.html进行抓取
4、对网站目录结构进行分析
大多数网站都会存在明确的 toptodown 的分类目录结构,我们可以进入特定行抓取
对于 www.mafengwo.cn这个网站,所有旅游的记都位于 www.mafengwo.cn/mdd下,按照城市进 行了分类,每个城市的游记位于首页。
城市的首页: /travel-scenic scenic-spot/mafengwo/10774 .html
游记的分页格式: /yj /10774/1-0-01 .html
游记的页面: /i/3523364.html
继续阅读 »
一、HTTP协议及HTML相关技术
(一)、HTTP协议

image.png


1.png


2.png



 
(二)、HTTP HEADER


image.png


红色标记比较重要
Keep-Alive功能使客户端到服务器的连接持续有效,当出现对后继请求时, Keep-Alive功能避免了建立或者重新建立连接。
HTTP/1.1默认所有情况下在HTTP1.1中所有连接都被保持,除非在请求头或响应头中指明要关闭:Connection:Close

image.png


(三)、HTTP请求方法

image.png


(四)、HTTP响应状态码
1、2XX  成功
2、3XX  跳转
3、4XX  客户端错误
4、5XX  服务器错误
 
300
1、300 Multiple Choices 存在多个可用的资源,处理或丢弃
2、301 Moved Permanetly重定向
3、302 Found 重定向
4、304 Not Modified 请求的资源未更新,丢弃
一些 Python 库,例如urllib2已结对重定向做了处理,会自动跳转;动态网页处理的时候也是自动跳转,所以不需要单独处理。
 
400、500
1、400 Bad Request客户端请求有语法错误,不能被服务器所 请求有语法错误,不能被服务器所理解
2、401 Unauthorized请求未经授权,这个状态代码必须和 WWW-Authenticate报头域一起使用
3、403 Forbidden服务器收到请求,但是拒绝提供 服务
4、404 Not Found请求资源不存在, eg :输入了错误的URL
5、 500 Internal Server Error服务器 发生不可预期的错误
6、503 Server Unavailable服务器当前不能处理客户端的请求,一段时间后可能恢复正常
 
错误处理
1、400 Bad Request 检查请求的参数或者路径
2、401 Unauthorized如果需要授权的网页,尝试重新登录
3、403 ForbiddenForbidden Forbidden
(1)如果是需要登录的网站,尝试重新登录
(2)IP 被封,暂停爬取并增加虫的等待时间,如果拨号网络尝试重新联网更改 IP
4、404 Not Found 直接丢弃
6、5XX 服务器错误, 直接丢弃,并计数,如果连续不成功,WARNING并停止爬取
 
(五)、HTML及CSS


image.png


image.png


HTML 超文本标记语言,简单来说可以认为一种规范或者协议浏 览器根据HTML的语言规范来解析
HTML里与爬虫相关的规范有以下:
这一类 tagtag 标记了外链用来做抓取,而 tr 、p用来进行内容抽取
• Tag:<a> <tr > <p >
id 、class 用在 css 上的,能帮助我们定位元素,作用于tr p 类似:
• Class: class=“home -price”
• Id: id=‘price -frame’ 
 
(六)、DOM树


image.png


(七)、Javascript
Javascript就是运行在前端的编程语言,最典型用动态网页数据、内容加载及呈现上, javascript做网络请求的时候最常用技术成为AJAX(Asynchronous JavaScript and XML),专门用来异步请求数据,这些是我们抓取的时候需要用到的。
 
二、宽度及深度抓取
(一)、网页抓取原理

image.png


(二)、爬虫的抓取对象类型
1、静态网页
2、动态网页
3、Web Service
(三)、深度优先策略


image.png


 
(四)、宽度优先策略


image.png


 
(五)、选择哪种策略
1、重要的网页距离种子站点比较近
2、 万维网的深度并没有很,一个页多路径可以到达 
3、 宽度优先有利于多爬虫并行合作抓取
4、深度限制于宽度优先相结合
 
三、不重复抓取策略
(一)、如何记录抓取历史
1. 将访问过的URL保存到数据库效率太低
2. 用HashSet HashSet 将访问过的 URL 保存起来。那只需接近 O(1)的代价就可以查到一个 URL是否被访问过了。 消耗内存
3. URL 经过 MD5 或SHA -1等单向哈希后再保存到 HashSet 或数据库。
4. Bit-Map方法。建立一个 BitSet ,将每个 URL 经过一个哈希函数映射到某一位。
(二)、MD5函数
MD5 签名是一个哈希函数,可以将任意长度的据量转换为固定长度数字,(通常是 4个整型, 128 位)。计算机不可能有 2的128 那么大内存,因此实际的哈 希表都会是 URL.MD5再%n (即取模)。现实世界的URL组合必然超越哈希表的槽位数,因此碰撞是一定存在的,一般的Hash函数,例如Java的HashTable是一 个HASH 表再跟上一个链表,链表里存的是碰撞的结果。

image.png


(三)、提高效率
1、评估网站的页数量
2、选择合适的 HASH 算法和空间阈值, 降低碰撞几率
3、选择合适的存储结构和算法
(四)、评估网页数量
site:网址
(五)、BITMAP方式记录
将URL的MD5值再次哈希,用一个或多BIT位来记录一个URL :
1. 确定空间大小 e.g.  facebook 1.5Gb
2. 按倍增加槽位 e.g. 16GB
3. HASH算法映射 ( murmurhash3, cityhash)Python: mmh3 bitarray
 
pip install murmurhash3 bitarray


image.png



• 优势:对存储进行了进一步压缩,在 MD5 的基础上,可以从 128 位最多压缩到 1位,一般情况如果用 4bit或者 8bit表示一个 url ,也能压缩 32 或者 16 倍
• 缺陷 :碰撞概率增加
(六)、Bloom Filter 
Bloom Filter使用了多个哈希函数,而不是一个。 创建一个 m位BitSet,先将所有位初始化为 0,然后选择 k个不同的哈希函数。第 i个哈希函数对字符串str哈希的结果记为 h(i,str ),且 h(i,str )的范围是 0到m-1。
只能插入,不能删除!!


image.png


(七)、pybloomfilter
安装
pip install pybloomfilter(可能运行时会 crash crash )
git clone https://github.com/axiak/pybloomfiltermmap.git 
python setup.py install
构造函数
class pybloomfilter.BloomFilter(capacity : int, error_rate:float[,filename=None:String][, perm=0755 ])
并不实际检查容量,如果需要比较低的error_rate,则需要设置更大的容量


image.png



官方文档
https://media.readthedocs.org/pdf/pybloomfiltermmap3/latest/pybloomfiltermmap3.pdf 
 
(八)、如何有效记录抓取历史
1、多数情况下不需要压缩,尤其网页量少的
2、网页数量大的情况下,使用 Bloom Filter压缩
3、重点是计算碰撞概率,并根据来确定存储空间的阈值
4、分布式系统、将散列映射到多台主机的内存
 
四、网站结构分析
1、网站对爬虫的限制
2、利用sitemap来分析网站结构和估算目标网页的规模
3、有效率抓取特定内容
      利用sitemap里的信息,直接对网页.html进行抓取
4、对网站目录结构进行分析
大多数网站都会存在明确的 toptodown 的分类目录结构,我们可以进入特定行抓取
对于 www.mafengwo.cn这个网站,所有旅游的记都位于 www.mafengwo.cn/mdd下,按照城市进 行了分类,每个城市的游记位于首页。
城市的首页: /travel-scenic scenic-spot/mafengwo/10774 .html
游记的分页格式: /yj /10774/1-0-01 .html
游记的页面: /i/3523364.html 收起阅读 »

第七课 面向对象(下)和异常处理

       因为周六晚上带孩子上辅导班,这次课是周日补的,笔记也是补的,左边是示例,右边知识点;上了这么七次课,感觉学到了很多学校课堂学不到的东西,就是对待一个项目的设计思想,给老师点赞,给小象点赞。
IMG_1525(20180423-151023).jpg


IMG_1526(20180423-151030).jpg


IMG_1527(20180423-151041).jpg


IMG_1528(20180423-151047).jpg


IMG_1529(20180423-151055).jpg


IMG_1530(20180423-151101).jpg
继续阅读 »
       因为周六晚上带孩子上辅导班,这次课是周日补的,笔记也是补的,左边是示例,右边知识点;上了这么七次课,感觉学到了很多学校课堂学不到的东西,就是对待一个项目的设计思想,给老师点赞,给小象点赞。
IMG_1525(20180423-151023).jpg


IMG_1526(20180423-151030).jpg


IMG_1527(20180423-151041).jpg


IMG_1528(20180423-151047).jpg


IMG_1529(20180423-151055).jpg


IMG_1530(20180423-151101).jpg
收起阅读 »

第七课

链接:http://note.youdao.com/notesha ... 7266E
如有错误,请指出,谢谢!!
下面是脑图:
类.png


包和模块_(1).png


异常处理.png

 
继续阅读 »
链接:http://note.youdao.com/notesha ... 7266E
如有错误,请指出,谢谢!!
下面是脑图:
类.png


包和模块_(1).png


异常处理.png

  收起阅读 »

#奶茶作业#第四、第五次作业

根据要求完成后,添加了日志管理,以及奶茶推荐,奶茶推荐做的比较粗糙,是分析所有已经购买的客户后,根据最喜欢这个奶茶的所有客户第二喜欢的奶茶来进行推荐,感觉不用dataframe和SQL操作起来还是很费劲,谢谢。(源码太长了超限制了,放有道了)
 
'''
奶茶店
第四次作业修改
'''
 
import csv
import time
import os
 
 
#欢迎语
welcomeWord = '小象奶茶店馆售卖宇宙无敌奶茶,奶茶虽好可不要贪杯哦!每次限尝鲜一种口味:'
naichaWord = '1.原味奶茶 3元 2.香蕉奶茶 5元 3.草莓奶茶 5元 4.香芋奶茶 7元 5.珍珠冰奶茶 7元'
sorryWord1 = 'Woops!我们只售卖以上'
sorryWord2 = '种奶茶口味哦!新口味敬请期待!'
naicha = {'1':'原味奶茶','2':'香蕉奶茶','3':'草莓奶茶','4':'香芋奶茶','5':'珍珠冰奶茶'}
naichaCost = {'1':3,'2':5,'3':5,'4':7,'5':7}
f_log_user='user_log.csv'
f_info_user='infoUsers.csv'
f_log_recome = 'log_recome.csv'
f_like_user='like_users.csv'
#print(len(naicha))
 
#设置会员 会员文件名称为 infoUsers.csv
members =
membersLog =
mphone = {}
 
class Users:
id=None
phone=None
birthday=None
sex=None
constellation=None
adress=None
with open(f_info_user,'a',encoding='utf-8') as info_file:
pass
#log=None 思考后觉得奶茶日志放在users类里以后不好维护
 
#判断是否为存在用户
def is_user(self,id):
with open('infoUsers.csv','r',encoding='utf-8') as info_file:
reader = csv.reader(info_file)
for row in reader:
if row[0]==id:
return True
return False
#获取用户文件行数
def get_infoUser_line(self):
with open(f_info_user,'r',encoding='utf-8') as info_files:
reader=csv.reader(info_files)
i = 0
for row in reader:
i += 1
print(i)
return i
#写入属性
def put_info(self,id,phone,birthday,sex,constellation,adress):
self.id=id
self.phone=phone
self.birthday=birthday
self.sex=sex
self.constellation=constellation
self.adress=adress
#将属性写入文件
def write_info(self):
header = ['id', 'phone', 'birthday', 'sex', 'constellation', 'adress']
with open (f_info_user, 'a', newline='', encoding='utf-8') as info_file:
writer = csv.DictWriter (info_file, header)
#writer.writeheader ()
writer.writerow (
{'id': self.id, 'phone': self.phone, 'birthday': self.birthday, 'sex': self.sex, 'constellation': self.constellation,
'adress': self.adress})
#读取use对象数值
def get_info(self):
return {'id':self.id,'phone':self.phone,'birthday':self.birthday,'sex':self.sex,'constellation':self.constellation,'adress':self.adress}
# def get_naichalog(self,):
# pass
 
#日志类,记录正常日志和每个奶茶的的购买情况
#daytime->日期,daylog->列表,就是每次的购买情况
class NaichaLog:
#判断日志名称
strtime=time.strftime('%Y%m%d',time.localtime())
log_file_name='naicha_log_'+strtime+'.csv'
#用户日志
user_log_name=f_log_user
#判断日志是否存在后,创建日志
if os.path.exists(log_file_name):
pass
else:
header=['id','time']
for key in naicha.keys():
header.append(key)
with open(log_file_name,'w',encoding='utf-8') as log_file:
writer=csv.writer(log_file)
writer.writerow(header)
if os.path.exists(user_log_name):
pass
else:
header=['id']
for key in naicha.keys():
header.append(key)
with open (log_file_name, 'w', encoding='utf-8') as log_file:
writer = csv.writer (log_file)
writer.writerow(header)
 
#print(log_file_name)
#写入每日日志
def writeDayLog(self, userid, daylog):
with open(self.log_file_name,'a',encoding='utf-8') as log_file:
writer=csv.writer(log_file)
naichaList=[userid,time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())]
for key in naicha.keys():
naichaList.append(daylog.setdefault(key,0))
writer.writerow(naichaList)
#写入用户购买日志
def writeUserLog(self,userid,naichalog):
with open(self.user_log_name,'a',encoding='utf-8') as log_file:
#reader=csv.reader(log_file)
writer=csv.writer(log_file)
newrow=[userid]
for key in naicha.keys():
newrow.append(naichalog[key])
print(newrow)
writer.writerow(newrow)
#newrow2 = [userid]
# for key in naicha.keys ():
# newrow2.append(naichalog.setdefault(key, 0))
# writer.writerow(newrow2)
 
#读取每日日志
def readDayLog(self,daytime):
pass
#读取用户购买日志
def readUserLog(self,userid):
pass
 
#推荐函数,在顾客购买之前推荐顾客经常买的奶茶,在顾客购买之后,推荐口味相似的客户购买的奶茶
#每日购物流水为 daylog_2018XXXX.csv
#顾客购买奶茶具体数据文件名称 logUsers.csv
#在关店后调用,根据后台信息计算口味相似顾客可能购买的1种奶茶
#先找出用户购买数量最多和第二多的奶茶,然后将每种奶茶买的最多的用户进行汇总,找出除了他们买的占比数量最多的第二多的奶茶,并再下次购买时推荐给客户
#将数据库中的每种奶茶购买最多的用户数据取出,将数据中除了此种奶茶的其他奶茶的按照一个客户一分计分,
# 计分后,分值除以用户总数,得出一个百分数,取出前两位数值,若数值高于80%,则给予用户推荐。
#计算顾客最喜欢的奶茶
def getUsersFisrstNaicha():
print('开始计算推荐...')
 
#writefilename = time.strftime ('log_recome_%Y%m%d.csv', time.localtime ())
 
writefile = open (f_log_recome, 'w', encoding='utf-8')
writer = csv.writer (writefile)
infofile = open (f_info_user, 'r', encoding='utf-8')
inreader = csv.reader (infofile)
recomelist =
 
for row in inreader:
new = [row[0], 0, 0, 0, 0, 0]
logfile = open (f_log_user, 'r', encoding='utf-8')
freader = csv.reader (logfile)
for row2 in freader:
if row2[0] == row[0]:
i = 1
while i < len (new):
new[i] = new[i] + int(row2[i])
i+=1
new2=new[1:len(new)]
i=0
j=0
while i < len(new2):
if max(new2)==new2[i]:
maxitem=i+1
new3=new2
new3.remove(new2[i])
while j < len(new2):
if max(new3)==new2[j] and j!=i :
maxitem2=j+1
break
j+=1
break
i+=1
#new2.sort()
# print(new2)
new.append(str(maxitem))
new.append(str(maxitem2))
recomelist.append(new)
logfile.close()
writer.writerows (recomelist)
writefile.close()
infofile.close()
print('计算完毕')
 
 
def showUsersRecomNaicha():
allRecome={}
for key in naicha.keys():
showUserLike = {'1':0,'2':0,'3':0,'4':0,'5':0}#.................妥协= =
logfile = open (f_log_recome, 'r', encoding='utf-8')
reader = csv.reader (logfile)
for row in reader:
if row[len(naicha)+1]==key :
showUserLike[row[len(naicha)+2]]+=1
maxkeyTuple=max(zip(showUserLike.values(),showUserLike.keys()))
maxkey=maxkeyTuple[1]
allRecome[key]=maxkey
logfile.close
with open(f_like_user,'w',encoding='utf-8') as likefile:
writer=csv.DictWriter(likefile,naicha.keys())
writer.writeheader()
writer.writerow(allRecome)
 
def getUserMostBuy(userid):
with open(f_log_recome,'r') as logfile:
reader=csv.reader(logfile)
for row in reader:
if row[0]==userid:
return row[len(naicha)+1]
 
#给客户推荐其他口味的奶茶
def getUsersRecomNaicha(key):
with open(f_like_user,'r') as likefile:
reader=csv.reader(likefile)
header=next(reader)
value=next(reader)
return value[int(key)-1]
 
#购物信息
costPerson =
costAllLog =
 
#设置固定客户数
costerNo = 2
fmemberNo = 37000
 
#设置购物函数
def shopping(member):
buyNo = input ('请输入购买序号:')
 
if buyNo not in naicha:
print (sorryWord1 + '{}'.format (len (naicha.keys ())) + sorryWord2)
else:
buyNumber = int (input ('请输入购买数量:'))
return [member,buyNo,buyNumber]
 
#设置输出购物结果函数
def shoppingPrint(member,shRecord,isnew):
allCost=0
if isnew:
sale=1
else:
sale=0.9
for key in shRecord.keys():
#print(shRecord[key])
#print(type(shRecord[key]))
#print(naichaCost)
allCost=naichaCost[key]*shRecord[key]
allCost*=sale
print('您本次购物购买了:')
for key in shRecord.keys():
print(' {} {}件'.format(naicha[key],shRecord[key]))
print('本次您总共消费了{}元,欢迎您的下次光临!'.format(allCost))
 
#设置购物详情记录函数
def shoppingLog(member,shRecord):
log=
log.append(member)
log.append(shRecord)
return log
 
 
#主程序开始
 
print(welcomeWord)
print(naichaWord)
 
while costerNo>0:
isnew=True
user =Users()
logs=NaichaLog()
 
now = input('\n 请输入会员号(没有会员号请输入 N):')
if now=='N' :
now = str(fmemberNo+user.get_infoUser_line())
print('您的会员号是:{}'.format(now))
phone = input('请输入您的手机号:')
user.put_info(now,phone,'','','','')
user.write_info()
else:
#print(members)
if user.is_user(now):
isnew = False
print ('Welcome {}'.format (now))
else:
isExist = input ('系统里没有此会员号,重新输入请输 Y ,系统分配请输 任意值: ')
if now == 'Y':
now = input ('请输入重新输入会员号:')
else:
now = str (fmemberNo + user.get_infoUser_line ())
print ('您的会员号是:{}'.format (now))
phone = input ('请输入您的手机号:')
user.put_info (now, phone, '', '', '', '')
user.write_info ()
# print(naicha.keys())
 
 
#开始购物
isQuit='i'
# 输出推荐购买
mostbuy = getUserMostBuy (now)
print ('小象记得您最喜欢的奶茶是 {} 哦~也推荐您尝试 {} ,偶尔换换新口味~'.format (naicha[mostbuy], naicha[getUsersRecomNaicha (mostbuy)]))
 
shoppingPersonRecord={}
while isQuit !='q':
naichaNow=shopping(now)
if naichaNow[1] in shoppingPersonRecord:
shoppingPersonRecord[naichaNow[1]]+=int(naichaNow[2])
else:
shoppingPersonRecord[naichaNow[1]]=int(naichaNow[2])
isQuit=input('是否继续购物?(继续 c/退出 q)')
 
#print(shoppingPersonRecord)
 
#输出购买
shoppingPrint(now,shoppingPersonRecord,isnew)
logs.writeDayLog(now,shoppingPersonRecord)
logs.writeUserLog(now,shoppingPersonRecord)
 
costPerson=(shoppingLog(now,shoppingPersonRecord))
costAllLog.append(costPerson)
costerNo -= 1
 
print('今日已闭店,欢迎您明天光临!')
#重新计算推荐算法,并生成日志
getUsersFisrstNaicha()
showUsersRecomNaicha()
#结账后输出交易明细
isMaster =input('进入贤者模式,请输入密码:')
while isMaster!='whoisyourdady':
isMaster=input('输入密码错误请重新输入:')
print(costAllLog)
 
 
 
继续阅读 »
根据要求完成后,添加了日志管理,以及奶茶推荐,奶茶推荐做的比较粗糙,是分析所有已经购买的客户后,根据最喜欢这个奶茶的所有客户第二喜欢的奶茶来进行推荐,感觉不用dataframe和SQL操作起来还是很费劲,谢谢。(源码太长了超限制了,放有道了)
 
'''
奶茶店
第四次作业修改
'''
 
import csv
import time
import os
 
 
#欢迎语
welcomeWord = '小象奶茶店馆售卖宇宙无敌奶茶,奶茶虽好可不要贪杯哦!每次限尝鲜一种口味:'
naichaWord = '1.原味奶茶 3元 2.香蕉奶茶 5元 3.草莓奶茶 5元 4.香芋奶茶 7元 5.珍珠冰奶茶 7元'
sorryWord1 = 'Woops!我们只售卖以上'
sorryWord2 = '种奶茶口味哦!新口味敬请期待!'
naicha = {'1':'原味奶茶','2':'香蕉奶茶','3':'草莓奶茶','4':'香芋奶茶','5':'珍珠冰奶茶'}
naichaCost = {'1':3,'2':5,'3':5,'4':7,'5':7}
f_log_user='user_log.csv'
f_info_user='infoUsers.csv'
f_log_recome = 'log_recome.csv'
f_like_user='like_users.csv'
#print(len(naicha))
 
#设置会员 会员文件名称为 infoUsers.csv
members =
membersLog =
mphone = {}
 
class Users:
id=None
phone=None
birthday=None
sex=None
constellation=None
adress=None
with open(f_info_user,'a',encoding='utf-8') as info_file:
pass
#log=None 思考后觉得奶茶日志放在users类里以后不好维护
 
#判断是否为存在用户
def is_user(self,id):
with open('infoUsers.csv','r',encoding='utf-8') as info_file:
reader = csv.reader(info_file)
for row in reader:
if row[0]==id:
return True
return False
#获取用户文件行数
def get_infoUser_line(self):
with open(f_info_user,'r',encoding='utf-8') as info_files:
reader=csv.reader(info_files)
i = 0
for row in reader:
i += 1
print(i)
return i
#写入属性
def put_info(self,id,phone,birthday,sex,constellation,adress):
self.id=id
self.phone=phone
self.birthday=birthday
self.sex=sex
self.constellation=constellation
self.adress=adress
#将属性写入文件
def write_info(self):
header = ['id', 'phone', 'birthday', 'sex', 'constellation', 'adress']
with open (f_info_user, 'a', newline='', encoding='utf-8') as info_file:
writer = csv.DictWriter (info_file, header)
#writer.writeheader ()
writer.writerow (
{'id': self.id, 'phone': self.phone, 'birthday': self.birthday, 'sex': self.sex, 'constellation': self.constellation,
'adress': self.adress})
#读取use对象数值
def get_info(self):
return {'id':self.id,'phone':self.phone,'birthday':self.birthday,'sex':self.sex,'constellation':self.constellation,'adress':self.adress}
# def get_naichalog(self,):
# pass
 
#日志类,记录正常日志和每个奶茶的的购买情况
#daytime->日期,daylog->列表,就是每次的购买情况
class NaichaLog:
#判断日志名称
strtime=time.strftime('%Y%m%d',time.localtime())
log_file_name='naicha_log_'+strtime+'.csv'
#用户日志
user_log_name=f_log_user
#判断日志是否存在后,创建日志
if os.path.exists(log_file_name):
pass
else:
header=['id','time']
for key in naicha.keys():
header.append(key)
with open(log_file_name,'w',encoding='utf-8') as log_file:
writer=csv.writer(log_file)
writer.writerow(header)
if os.path.exists(user_log_name):
pass
else:
header=['id']
for key in naicha.keys():
header.append(key)
with open (log_file_name, 'w', encoding='utf-8') as log_file:
writer = csv.writer (log_file)
writer.writerow(header)
 
#print(log_file_name)
#写入每日日志
def writeDayLog(self, userid, daylog):
with open(self.log_file_name,'a',encoding='utf-8') as log_file:
writer=csv.writer(log_file)
naichaList=[userid,time.strftime('%Y-%m-%d %H:%M:%S',time.localtime())]
for key in naicha.keys():
naichaList.append(daylog.setdefault(key,0))
writer.writerow(naichaList)
#写入用户购买日志
def writeUserLog(self,userid,naichalog):
with open(self.user_log_name,'a',encoding='utf-8') as log_file:
#reader=csv.reader(log_file)
writer=csv.writer(log_file)
newrow=[userid]
for key in naicha.keys():
newrow.append(naichalog[key])
print(newrow)
writer.writerow(newrow)
#newrow2 = [userid]
# for key in naicha.keys ():
# newrow2.append(naichalog.setdefault(key, 0))
# writer.writerow(newrow2)
 
#读取每日日志
def readDayLog(self,daytime):
pass
#读取用户购买日志
def readUserLog(self,userid):
pass
 
#推荐函数,在顾客购买之前推荐顾客经常买的奶茶,在顾客购买之后,推荐口味相似的客户购买的奶茶
#每日购物流水为 daylog_2018XXXX.csv
#顾客购买奶茶具体数据文件名称 logUsers.csv
#在关店后调用,根据后台信息计算口味相似顾客可能购买的1种奶茶
#先找出用户购买数量最多和第二多的奶茶,然后将每种奶茶买的最多的用户进行汇总,找出除了他们买的占比数量最多的第二多的奶茶,并再下次购买时推荐给客户
#将数据库中的每种奶茶购买最多的用户数据取出,将数据中除了此种奶茶的其他奶茶的按照一个客户一分计分,
# 计分后,分值除以用户总数,得出一个百分数,取出前两位数值,若数值高于80%,则给予用户推荐。
#计算顾客最喜欢的奶茶
def getUsersFisrstNaicha():
print('开始计算推荐...')
 
#writefilename = time.strftime ('log_recome_%Y%m%d.csv', time.localtime ())
 
writefile = open (f_log_recome, 'w', encoding='utf-8')
writer = csv.writer (writefile)
infofile = open (f_info_user, 'r', encoding='utf-8')
inreader = csv.reader (infofile)
recomelist =
 
for row in inreader:
new = [row[0], 0, 0, 0, 0, 0]
logfile = open (f_log_user, 'r', encoding='utf-8')
freader = csv.reader (logfile)
for row2 in freader:
if row2[0] == row[0]:
i = 1
while i < len (new):
new[i] = new[i] + int(row2[i])
i+=1
new2=new[1:len(new)]
i=0
j=0
while i < len(new2):
if max(new2)==new2[i]:
maxitem=i+1
new3=new2
new3.remove(new2[i])
while j < len(new2):
if max(new3)==new2[j] and j!=i :
maxitem2=j+1
break
j+=1
break
i+=1
#new2.sort()
# print(new2)
new.append(str(maxitem))
new.append(str(maxitem2))
recomelist.append(new)
logfile.close()
writer.writerows (recomelist)
writefile.close()
infofile.close()
print('计算完毕')
 
 
def showUsersRecomNaicha():
allRecome={}
for key in naicha.keys():
showUserLike = {'1':0,'2':0,'3':0,'4':0,'5':0}#.................妥协= =
logfile = open (f_log_recome, 'r', encoding='utf-8')
reader = csv.reader (logfile)
for row in reader:
if row[len(naicha)+1]==key :
showUserLike[row[len(naicha)+2]]+=1
maxkeyTuple=max(zip(showUserLike.values(),showUserLike.keys()))
maxkey=maxkeyTuple[1]
allRecome[key]=maxkey
logfile.close
with open(f_like_user,'w',encoding='utf-8') as likefile:
writer=csv.DictWriter(likefile,naicha.keys())
writer.writeheader()
writer.writerow(allRecome)
 
def getUserMostBuy(userid):
with open(f_log_recome,'r') as logfile:
reader=csv.reader(logfile)
for row in reader:
if row[0]==userid:
return row[len(naicha)+1]
 
#给客户推荐其他口味的奶茶
def getUsersRecomNaicha(key):
with open(f_like_user,'r') as likefile:
reader=csv.reader(likefile)
header=next(reader)
value=next(reader)
return value[int(key)-1]
 
#购物信息
costPerson =
costAllLog =
 
#设置固定客户数
costerNo = 2
fmemberNo = 37000
 
#设置购物函数
def shopping(member):
buyNo = input ('请输入购买序号:')
 
if buyNo not in naicha:
print (sorryWord1 + '{}'.format (len (naicha.keys ())) + sorryWord2)
else:
buyNumber = int (input ('请输入购买数量:'))
return [member,buyNo,buyNumber]
 
#设置输出购物结果函数
def shoppingPrint(member,shRecord,isnew):
allCost=0
if isnew:
sale=1
else:
sale=0.9
for key in shRecord.keys():
#print(shRecord[key])
#print(type(shRecord[key]))
#print(naichaCost)
allCost=naichaCost[key]*shRecord[key]
allCost*=sale
print('您本次购物购买了:')
for key in shRecord.keys():
print(' {} {}件'.format(naicha[key],shRecord[key]))
print('本次您总共消费了{}元,欢迎您的下次光临!'.format(allCost))
 
#设置购物详情记录函数
def shoppingLog(member,shRecord):
log=
log.append(member)
log.append(shRecord)
return log
 
 
#主程序开始
 
print(welcomeWord)
print(naichaWord)
 
while costerNo>0:
isnew=True
user =Users()
logs=NaichaLog()
 
now = input('\n 请输入会员号(没有会员号请输入 N):')
if now=='N' :
now = str(fmemberNo+user.get_infoUser_line())
print('您的会员号是:{}'.format(now))
phone = input('请输入您的手机号:')
user.put_info(now,phone,'','','','')
user.write_info()
else:
#print(members)
if user.is_user(now):
isnew = False
print ('Welcome {}'.format (now))
else:
isExist = input ('系统里没有此会员号,重新输入请输 Y ,系统分配请输 任意值: ')
if now == 'Y':
now = input ('请输入重新输入会员号:')
else:
now = str (fmemberNo + user.get_infoUser_line ())
print ('您的会员号是:{}'.format (now))
phone = input ('请输入您的手机号:')
user.put_info (now, phone, '', '', '', '')
user.write_info ()
# print(naicha.keys())
 
 
#开始购物
isQuit='i'
# 输出推荐购买
mostbuy = getUserMostBuy (now)
print ('小象记得您最喜欢的奶茶是 {} 哦~也推荐您尝试 {} ,偶尔换换新口味~'.format (naicha[mostbuy], naicha[getUsersRecomNaicha (mostbuy)]))
 
shoppingPersonRecord={}
while isQuit !='q':
naichaNow=shopping(now)
if naichaNow[1] in shoppingPersonRecord:
shoppingPersonRecord[naichaNow[1]]+=int(naichaNow[2])
else:
shoppingPersonRecord[naichaNow[1]]=int(naichaNow[2])
isQuit=input('是否继续购物?(继续 c/退出 q)')
 
#print(shoppingPersonRecord)
 
#输出购买
shoppingPrint(now,shoppingPersonRecord,isnew)
logs.writeDayLog(now,shoppingPersonRecord)
logs.writeUserLog(now,shoppingPersonRecord)
 
costPerson=(shoppingLog(now,shoppingPersonRecord))
costAllLog.append(costPerson)
costerNo -= 1
 
print('今日已闭店,欢迎您明天光临!')
#重新计算推荐算法,并生成日志
getUsersFisrstNaicha()
showUsersRecomNaicha()
#结账后输出交易明细
isMaster =input('进入贤者模式,请输入密码:')
while isMaster!='whoisyourdady':
isMaster=input('输入密码错误请重新输入:')
print(costAllLog)
 
 
  收起阅读 »

第六课(类)

以下是链接:http://note.youdao.com/notesha ... 94C2D
如果错误,请指出,谢谢!
 
下面是脑图
类.png

 
继续阅读 »
以下是链接:http://note.youdao.com/notesha ... 94C2D
如果错误,请指出,谢谢!
 
下面是脑图
类.png

  收起阅读 »

第六课 - 面向对象编程

# 面向对象编程
**面向对象编程**,简称OOP:是一种解决软件服用的设计和编程方法。这种方法把软件系统中相似的逻辑操作、数据、状态等以类的形式描述出来,通过对象实例在软件系统中复用,从而提高软件开发效率。

# 类和对象
**定义和关系**
**类**:一个事物的抽象,定义了一类事物的属性和行为。类具有继承,多态,封装等特性。
```
class 类名: #类命名规则遵守“大驼峰”
#默认要传入一个self参数,第一个参数必须是sel
def 方法名(self [, 参数列表]):
```
**对象**:通过类创建的一个具体事物,也就是类的实例,它具有状态和行为,可以做具体的事情。
```
对象变量名 = 类名()
```
**两者关系**:类相当于创建对象的模板,根据类可以创建一个或者多个对象实例。

# 类的方法
**类的构造方法**
_ _init_ _构造方法:用于对象创建时初始化
调用时间:在对象被实例化时被程序自动调用
程序不显示定义init方法,则程序默认调用一个无参init方法
对象创建过程示意图:
![](http://wenda.chinahadoop.cn/up ... 07.png)

**类的私有方法**
只能在类内部调用,在类的外部无法调用
私有方法:在方法名前添加两个下划线,私有属性如是
类内部调用私有方法要使用**self.private_method()**的方式调用
```
class Comrade:
#私有方法
def __send_message(self):
print("消息已经向上级汇报")

def answer_secret(self, secret):
if secret == "芝麻开门":
print("接头成功!")
self.__send_message()#调用私有方法
else:
print("接头失败!")
comrade = Comrade()
comrade.answer_secret("芝麻开门")
```
**类的访问权限**
```
#设置对象属性
def __init__(self, gender, variety, name):
self.gender = gender
self.variety = variety
self.name = name
```
修改对象属性有两种形式:
* 直接对属性值进行赋值
* 通过方法对属性值进行修改。这是推荐方式。可以达到对数据进行封装。


# 类的特性一:继承和多重继承
**继承**
定义:在程序中,子类从父类继承,但是子类又可以提供除父类外自身独有的方法和属性。比如猫和狗都是动物,动物如果是父类的话,那么猫和狗就是动物的子类。父类通常是抽象出带有一些共性的特征和方法的类。
```
#父类Animal
class Animal:
def eat():
print("eat")
#Dog
class Dog(Animal):
def shout()
print("汪汪汪")
wangcai = Dog()
#调用父类的eat
wangcai.eat()
#调用自身成员方法
wangcai.shout()
```
**继承注意事项**
* 子类的非有属性、方法,会被子类继承
* 子类中方法的查找:先子类方法 =》后父类方法
* 子类可以继承祖先类的非私有属性和方法
* 在子类中调用父类的方法:ClassName.Method(self)

**多重继承**
定义:一个类可以从多个父类继承。
多继承的定义方式:
```python
class AI:
#人脸识别
def face_recongnition(self):
print("人脸识别")
def data_handle(self):
print("AI数据处理")

class BigData:
def data_analysis(self):
print("数据分析")
def data_handle(self):
print("BigData数据处理")

class Python(BigData, AI): #多重继承,Python从BigData和AI两个类继承
def operation(self):
print("自动化运维")
```
对于多重继承,子类调用查找同名方法的顺序:
* 取决于小括号内继承父类从左到右的顺序查找。
* 可以通过类的方法 _ _mro_ _来查看查找顺序。

# 类的特性二:多态
定义:一个抽象类有多个子类,不同的类表现出不同的形态。比如狗和猫,他们都会叫,但是叫的声音是不同的。
子类对父类允许访问的方法的实现过程进行重新编写
在子类中定义与父类同名的方法。子类可以根据需要,定义合适的方法实现逻辑。

# 综合例子: 继承和多态
```
class Animal:
def __init__(self):
print("---animal构造方法---")

def __private_method(self):
print("私有方法")
def eat(self):
print("----吃----")
def drink(self):
print("----喝----")
def run(self):
print("----跑----")

class Dog(Animal):
def __init__(self):
print("dog构造方法")
#父类方法重写
def run(self): #多态
print("摇着尾巴跑")
def hand(self):
Animal.run(self) #在子类中调用父类
print("------握手-----")

class GoldenDog(Dog):
def guid(self):
print("我能导航!")
```
继续阅读 »
# 面向对象编程
**面向对象编程**,简称OOP:是一种解决软件服用的设计和编程方法。这种方法把软件系统中相似的逻辑操作、数据、状态等以类的形式描述出来,通过对象实例在软件系统中复用,从而提高软件开发效率。

# 类和对象
**定义和关系**
**类**:一个事物的抽象,定义了一类事物的属性和行为。类具有继承,多态,封装等特性。
```
class 类名: #类命名规则遵守“大驼峰”
#默认要传入一个self参数,第一个参数必须是sel
def 方法名(self [, 参数列表]):
```
**对象**:通过类创建的一个具体事物,也就是类的实例,它具有状态和行为,可以做具体的事情。
```
对象变量名 = 类名()
```
**两者关系**:类相当于创建对象的模板,根据类可以创建一个或者多个对象实例。

# 类的方法
**类的构造方法**
_ _init_ _构造方法:用于对象创建时初始化
调用时间:在对象被实例化时被程序自动调用
程序不显示定义init方法,则程序默认调用一个无参init方法
对象创建过程示意图:
![](http://wenda.chinahadoop.cn/up ... 07.png)

**类的私有方法**
只能在类内部调用,在类的外部无法调用
私有方法:在方法名前添加两个下划线,私有属性如是
类内部调用私有方法要使用**self.private_method()**的方式调用
```
class Comrade:
#私有方法
def __send_message(self):
print("消息已经向上级汇报")

def answer_secret(self, secret):
if secret == "芝麻开门":
print("接头成功!")
self.__send_message()#调用私有方法
else:
print("接头失败!")
comrade = Comrade()
comrade.answer_secret("芝麻开门")
```
**类的访问权限**
```
#设置对象属性
def __init__(self, gender, variety, name):
self.gender = gender
self.variety = variety
self.name = name
```
修改对象属性有两种形式:
* 直接对属性值进行赋值
* 通过方法对属性值进行修改。这是推荐方式。可以达到对数据进行封装。


# 类的特性一:继承和多重继承
**继承**
定义:在程序中,子类从父类继承,但是子类又可以提供除父类外自身独有的方法和属性。比如猫和狗都是动物,动物如果是父类的话,那么猫和狗就是动物的子类。父类通常是抽象出带有一些共性的特征和方法的类。
```
#父类Animal
class Animal:
def eat():
print("eat")
#Dog
class Dog(Animal):
def shout()
print("汪汪汪")
wangcai = Dog()
#调用父类的eat
wangcai.eat()
#调用自身成员方法
wangcai.shout()
```
**继承注意事项**
* 子类的非有属性、方法,会被子类继承
* 子类中方法的查找:先子类方法 =》后父类方法
* 子类可以继承祖先类的非私有属性和方法
* 在子类中调用父类的方法:ClassName.Method(self)

**多重继承**
定义:一个类可以从多个父类继承。
多继承的定义方式:
```python
class AI:
#人脸识别
def face_recongnition(self):
print("人脸识别")
def data_handle(self):
print("AI数据处理")

class BigData:
def data_analysis(self):
print("数据分析")
def data_handle(self):
print("BigData数据处理")

class Python(BigData, AI): #多重继承,Python从BigData和AI两个类继承
def operation(self):
print("自动化运维")
```
对于多重继承,子类调用查找同名方法的顺序:
* 取决于小括号内继承父类从左到右的顺序查找。
* 可以通过类的方法 _ _mro_ _来查看查找顺序。

# 类的特性二:多态
定义:一个抽象类有多个子类,不同的类表现出不同的形态。比如狗和猫,他们都会叫,但是叫的声音是不同的。
子类对父类允许访问的方法的实现过程进行重新编写
在子类中定义与父类同名的方法。子类可以根据需要,定义合适的方法实现逻辑。

# 综合例子: 继承和多态
```
class Animal:
def __init__(self):
print("---animal构造方法---")

def __private_method(self):
print("私有方法")
def eat(self):
print("----吃----")
def drink(self):
print("----喝----")
def run(self):
print("----跑----")

class Dog(Animal):
def __init__(self):
print("dog构造方法")
#父类方法重写
def run(self): #多态
print("摇着尾巴跑")
def hand(self):
Animal.run(self) #在子类中调用父类
print("------握手-----")

class GoldenDog(Dog):
def guid(self):
print("我能导航!")
``` 收起阅读 »

第六课 面向对象(中)

这次课程信息量巨大,知识点不多,个个都是精华。依旧左边示例,右边知识点。

IMG_1480(20180418-212850).jpg


IMG_1481(20180418-212857).jpg


IMG_1482(20180418-212904).jpg


IMG_1483(20180418-212911).jpg

 
继续阅读 »
这次课程信息量巨大,知识点不多,个个都是精华。依旧左边示例,右边知识点。

IMG_1480(20180418-212850).jpg


IMG_1481(20180418-212857).jpg


IMG_1482(20180418-212904).jpg


IMG_1483(20180418-212911).jpg

  收起阅读 »

第一章节:基础语法 课后作业

lis="""
***********************************************
    请输入您想购买的奶茶:
        1:原味冰奶茶  3元
        2:香蕉冰奶茶  5元
        3:草莓病奶茶  4元
        4:香草冰奶茶  7元
        5:珍珠冰奶茶  7元
***********************************************
    您是否是我店会员?会员享有9折优惠!
        T:是会员。
        F:不是会员。
        注:不区分大小写!
***********************************************
"""
dic = {'1':['原味冰奶茶',3],'2':['香蕉冰奶茶',5],'3':['草莓病奶茶',4],'4':['香草冰奶茶',7],'5':['珍珠冰奶茶',7]}
ty = ('1','2','3','4','5')
huiyuan = {'y':['是',0.9],'n':['否',1.0]}


name = input(lis)
if name in ty:
    num = int(input('请输入您想购买的数量:'))
    hy = input('会员?').lower()
    if hy=='y':
        zjia = dic[name][1]*num*0.9
    else:
        zjia = dic[name][1]*num
    print("*"*100)
    print('%5s %8s s s s %21s'%('类别','单价','数量','会员','折扣','总价'))
    print()
    print('%s %5s d s %21.1f %25.2f'%(dic[name][0],dic[name][1],num,huiyuan[hy][0],huiyuan[hy][1],zjia))
    print("*"*100)
else:
    print('Woops!我们只售卖以上五种奶茶哦,新口味敬请期待!')
继续阅读 »
lis="""
***********************************************
    请输入您想购买的奶茶:
        1:原味冰奶茶  3元
        2:香蕉冰奶茶  5元
        3:草莓病奶茶  4元
        4:香草冰奶茶  7元
        5:珍珠冰奶茶  7元
***********************************************
    您是否是我店会员?会员享有9折优惠!
        T:是会员。
        F:不是会员。
        注:不区分大小写!
***********************************************
"""
dic = {'1':['原味冰奶茶',3],'2':['香蕉冰奶茶',5],'3':['草莓病奶茶',4],'4':['香草冰奶茶',7],'5':['珍珠冰奶茶',7]}
ty = ('1','2','3','4','5')
huiyuan = {'y':['是',0.9],'n':['否',1.0]}


name = input(lis)
if name in ty:
    num = int(input('请输入您想购买的数量:'))
    hy = input('会员?').lower()
    if hy=='y':
        zjia = dic[name][1]*num*0.9
    else:
        zjia = dic[name][1]*num
    print("*"*100)
    print('%5s %8s s s s %21s'%('类别','单价','数量','会员','折扣','总价'))
    print()
    print('%s %5s d s %21.1f %25.2f'%(dic[name][0],dic[name][1],num,huiyuan[hy][0],huiyuan[hy][1],zjia))
    print("*"*100)
else:
    print('Woops!我们只售卖以上五种奶茶哦,新口味敬请期待!')
收起阅读 »

第五课笔记

第五课笔记:
http://note.youdao.com/notesha ... 6DAE1
 
如有错误,欢迎指出!! 谢谢!!
以下是脑图

CSV格式文件操作.png


日期与时间.png


JSON格式文件操作.png


面向对象编程.png

 
继续阅读 »
第五课笔记:
http://note.youdao.com/notesha ... 6DAE1
 
如有错误,欢迎指出!! 谢谢!!
以下是脑图

CSV格式文件操作.png


日期与时间.png


JSON格式文件操作.png


面向对象编程.png

  收起阅读 »

第五课 文件操作、面向对象(上)

       这一讲的内容相当丰富,记笔记记得手麻,还是喜欢手写笔记^_^。左边依旧是示例,右边仍然是知识点,请各位多多指教。
IMG_1410(20180413-200446).jpg


IMG_1411(20180413-200438).jpg


IMG_1412(20180413-200432).jpg


IMG_1413(20180413-200426).jpg


IMG_1414(20180413-200418).jpg


IMG_1415(20180413-200344).jpg


IMG_1422(20180413-200410).jpg
继续阅读 »
       这一讲的内容相当丰富,记笔记记得手麻,还是喜欢手写笔记^_^。左边依旧是示例,右边仍然是知识点,请各位多多指教。
IMG_1410(20180413-200446).jpg


IMG_1411(20180413-200438).jpg


IMG_1412(20180413-200432).jpg


IMG_1413(20180413-200426).jpg


IMG_1414(20180413-200418).jpg


IMG_1415(20180413-200344).jpg


IMG_1422(20180413-200410).jpg
收起阅读 »

第四课晓宁Python函数(下)笔记

#Python人工智能基础篇-第四课笔记
## 函数(下)
###1.局部变量

* 函数内部定义函数
* 不同函数内的局部变量可以定义相同的名字,互不影响
* 作用范围:函数体内有效,其他函数不能直接使用

####1.1 局部变量实例
#局部变量
def set_name():
name = "zhangsan"
return name

def get_name(name):
name = "lisi" //此处不修改name值,应该打印zhangsan
print(name)

nm = set_name()
get_name(nm) //输出结果“lisi”
###2.全局变量

* 函数外部定义的变量
* 作用范围:可以再不同函数中使用
* 在函数内使用global关键字实现修改全局变量的值
* 全局变量命名建议以g_开头,如g_game

####2.1全局变量实例
name = "zhangsan"
def get_name():
print(name)

def get_name2():
print(name)

get_name() //输出zhangsan
get_name2() //输出zhangsan
print(name) //输出zhangsan
####2.2在函数内使用global关键字
age = 20
def change_age():
global age
age = 25
print("函数体内age=%d"%age)//输出函数体内age=25

change_age()
print("函数体外age=%d"%age) //输出函数体外age=25

###3、函数参数
####3.1缺省参数

* 函数定义带有初始值的形参
* 函数调用时,缺省参数可传,也可不穿
* 缺省参数一定要位于参数列表的最后
* 缺省参数数量没有限制

#####3.1.1 缺省函数实例
#缺省参数
def x_y_sum(x,y=20):
print("x=%d"%x)
print("y=%d"%y)
return x + y
sum1 = x_y_sum(10)
print(sum1) //输出结果x=10,y=20 30
sum2 = x_y_sum(10,30)
print(sum2) //输出结果x=10,y=30 40

####3.2命名参数

* 调用带有参数的函数时,通过指定参数名称传入参数的值
* 可以不按函数定义的参数顺序传入
#####3.2.1 命名函数实例
def x_y_sum(x=10,y=20):
return x + y
#注意:函数调用的时候命名参数的名称与函数定义时的形参名称相同,但是顺序可以不同
rs1 = x_y_sum(y=30,x=15)
rs2 = x_y_sum(x=15)
rs3 = x_y_sum()

print("rs1=%d"%rs1) //输出结果rs1=45
print("rs2=%d"%rs2) //输出结果rs2=35
####3.3不定长参数


* 函数可以接受不定个数的参数传入
* def function([formal_args,]*args)函数调用时,传入的不定参数会被封装成元组
* def function([formal_args,]**args)函数调用时,如果传入key = value的形式的不定长参数,会被封装成字典

####3.3.1 第一种定义实例
#def fuction([formal_args,]*args)

#改变不定长参数的位置
def any_num_sum2(x,*args,y=10):
print("args={}".format(args))
print("x={}".format(x))
print("y={}".format(y))
rs = x + y
if len(args) > 0:
for arg in args:
rs += arg
return rs

rs1 = any_num_sum2(20)
rs2 = any_num_sum2(20,30,y=100)
rs3 = any_num_sum2(20,30,40,50,60,y=100)
print(rs1) //输出结果 args={},x=20,y=10 rs1=30
print(rs2) //输出结果 args=(30,) x=20 y=100 rs2=150
print(rs3) //输出结果 args=(30, 40, 50, 60) x=20 y=100 rs3=300
###4递归函数

* 函数调用自身
* 注意:递归过程中要有用于结束递归的判断

####4.1 递归函数实例
def recursive_for(num):
rs = num
for i in range(1,num):# (1,4) = [1,2,3)
rs *= i
return rs
result = recursive_for(4)
print(result) //输出结果24
继续阅读 »
#Python人工智能基础篇-第四课笔记
## 函数(下)
###1.局部变量

* 函数内部定义函数
* 不同函数内的局部变量可以定义相同的名字,互不影响
* 作用范围:函数体内有效,其他函数不能直接使用

####1.1 局部变量实例
#局部变量
def set_name():
name = "zhangsan"
return name

def get_name(name):
name = "lisi" //此处不修改name值,应该打印zhangsan
print(name)

nm = set_name()
get_name(nm) //输出结果“lisi”
###2.全局变量

* 函数外部定义的变量
* 作用范围:可以再不同函数中使用
* 在函数内使用global关键字实现修改全局变量的值
* 全局变量命名建议以g_开头,如g_game

####2.1全局变量实例
name = "zhangsan"
def get_name():
print(name)

def get_name2():
print(name)

get_name() //输出zhangsan
get_name2() //输出zhangsan
print(name) //输出zhangsan
####2.2在函数内使用global关键字
age = 20
def change_age():
global age
age = 25
print("函数体内age=%d"%age)//输出函数体内age=25

change_age()
print("函数体外age=%d"%age) //输出函数体外age=25

###3、函数参数
####3.1缺省参数

* 函数定义带有初始值的形参
* 函数调用时,缺省参数可传,也可不穿
* 缺省参数一定要位于参数列表的最后
* 缺省参数数量没有限制

#####3.1.1 缺省函数实例
#缺省参数
def x_y_sum(x,y=20):
print("x=%d"%x)
print("y=%d"%y)
return x + y
sum1 = x_y_sum(10)
print(sum1) //输出结果x=10,y=20 30
sum2 = x_y_sum(10,30)
print(sum2) //输出结果x=10,y=30 40

####3.2命名参数

* 调用带有参数的函数时,通过指定参数名称传入参数的值
* 可以不按函数定义的参数顺序传入
#####3.2.1 命名函数实例
def x_y_sum(x=10,y=20):
return x + y
#注意:函数调用的时候命名参数的名称与函数定义时的形参名称相同,但是顺序可以不同
rs1 = x_y_sum(y=30,x=15)
rs2 = x_y_sum(x=15)
rs3 = x_y_sum()

print("rs1=%d"%rs1) //输出结果rs1=45
print("rs2=%d"%rs2) //输出结果rs2=35
####3.3不定长参数


* 函数可以接受不定个数的参数传入
* def function([formal_args,]*args)函数调用时,传入的不定参数会被封装成元组
* def function([formal_args,]**args)函数调用时,如果传入key = value的形式的不定长参数,会被封装成字典

####3.3.1 第一种定义实例
#def fuction([formal_args,]*args)

#改变不定长参数的位置
def any_num_sum2(x,*args,y=10):
print("args={}".format(args))
print("x={}".format(x))
print("y={}".format(y))
rs = x + y
if len(args) > 0:
for arg in args:
rs += arg
return rs

rs1 = any_num_sum2(20)
rs2 = any_num_sum2(20,30,y=100)
rs3 = any_num_sum2(20,30,40,50,60,y=100)
print(rs1) //输出结果 args={},x=20,y=10 rs1=30
print(rs2) //输出结果 args=(30,) x=20 y=100 rs2=150
print(rs3) //输出结果 args=(30, 40, 50, 60) x=20 y=100 rs3=300
###4递归函数

* 函数调用自身
* 注意:递归过程中要有用于结束递归的判断

####4.1 递归函数实例
def recursive_for(num):
rs = num
for i in range(1,num):# (1,4) = [1,2,3)
rs *= i
return rs
result = recursive_for(4)
print(result) //输出结果24
收起阅读 »

第四课笔记(函数(下))

为了函数变为一张,我把函数上下合成了一篇笔记,一下是链接。
http://note.youdao.com/notesha ... 9B2F2
 

函数.png

 
继续阅读 »
为了函数变为一张,我把函数上下合成了一篇笔记,一下是链接。
http://note.youdao.com/notesha ... 9B2F2
 

函数.png

  收起阅读 »

第四课:函数

还请移步到有道云笔记分享:
 
https://note.youdao.com/share/ ... e%23/
 
还请移步到有道云笔记分享:
 
https://note.youdao.com/share/ ... e%23/
 

第四课 函数(下)

还是手写版的,右边知识点,左边示例


IMG_1401(20180412-153017).jpg


IMG_1402(20180412-153025).jpg


IMG_1403(20180412-153034).jpg


IMG_1404(20180412-153041).jpg


IMG_1405(20180412-153049).jpg


IMG_1406(20180412-153055).jpg

 
继续阅读 »
还是手写版的,右边知识点,左边示例


IMG_1401(20180412-153017).jpg


IMG_1402(20180412-153025).jpg


IMG_1403(20180412-153034).jpg


IMG_1404(20180412-153041).jpg


IMG_1405(20180412-153049).jpg


IMG_1406(20180412-153055).jpg

  收起阅读 »

#奶茶店#第三次作业(⊙﹏⊙)b


1523502045314.png

1523502076824.png

1523502109721.png

等看看讲解再修改一下,做的时候感觉题目理解偏了(⊙﹏⊙)b

1523502045314.png

1523502076824.png

1523502109721.png

等看看讲解再修改一下,做的时候感觉题目理解偏了(⊙﹏⊙)b