1.经过headers反爬虫
2.基于用户行为的发爬虫:(同一IP短期内访问的频率)
3.动态网页反爬虫(经过ajax请求数据,或者经过JavaScript生成)
4.对部分数据进行加密处理的(数据是乱码)html
对于基本网页的抓取能够自定义headers,添加headers的数据
使用多个代理ip进行抓取或者设置抓取的频率下降一些,
动态网页的可使用selenium + phantomjs 进行抓取
对部分数据进行加密的,可使用selenium进行截图,使用python自带的pytesseract库进行识别,可是比较慢最直接的方法是找到加密的方法进行逆向推理。python
headers方向
判断User-Agent、判断Referer、判断Cookie。
将浏览器的headers信息所有添加进去
注意:Accept-Encoding;gzip,deflate须要注释掉react
它是将scrapy框架中Scheduler替换为redis数据库,实现队列管理共享。jquery
分为5个部分;Spiders(爬虫类),Scrapy Engine(引擎),Scheduler(调度器),Downloader(下载器),Item Pipeline(处理管道)。web
对于一个可迭代的(iterable)/可遍历的对象(如列表、字符串),enumerate将其组成一个索引序列,利用它能够同时得到索引和值
enumerate多用于在for循环中获得计数ajax
无头浏览器即headless browser,是一种没有界面的浏览器。既然是浏览器那么浏览器该有的东西它都应该有,只是看不到界面而已。redis
Python中selenium模块中的PhantomJS即为***面浏览器(无头浏览器):是基于QtWebkit的无头浏览器。算法
scrapy是一个爬虫通用框架,但不支持分布式,scrapy-redis是为了更方便的实现scrapy分布式爬虫,而提供了一些以redis为基础的组件shell
由于redis支持主从同步,并且数据都是缓存在内存中,因此基于redis的分布式爬虫,对请求和数据的高频读取效率很是高数据库
在Redis中,用户能够经过执行SLAVEOF命令或者设置slaveof选项,让一个服务器去复制(replicate)另外一个服务器,咱们称呼被复制的服务器为主服务器(master),而对主服务器进行复制的服务器则被称为从服务器(slave),当客户端向从服务器发送SLAVEOF命令,要求从服务器复制主服务器时,从服务器首先须要执行同步操做,也便是,将从服务器的数据库状态更新至主服务器当前所处的数据库状态
采起可读性更强的xpath代替正则 强大的统计和log系统 同时在不一样的url上爬行 支持shell方式,方便独立调试 写middleware,方便写一些统一的过滤器 经过管道的方式存入数据库
基于python爬虫框架,扩展性比较差,基于twisted框架,运行中exception是不会干掉reactor,而且异步框架出错后是不会停掉其余任务的,数据出错后难以察觉
requests 是 polling 方式的,会被网络阻塞,不适合爬取大量数据
scapy 底层是异步框架 twisted ,并发是最大优点
从start_urls里面获取第一批url发送请求,请求由请求引擎给调度器入请求对列,获取完毕后,调度器将请求对列交给下载器去获取请求对应的响应资源,并将响应交给本身编写的解析方法作提取处理,若是提取出须要的数据,则交给管道处理,若是提取出url,则继续执行以前的步骤,直到多列里没有请求,程序结束。
IO密集型代码(文件处理、网络爬虫等),多线程可以有效提高效率(单线程下有IO操做会进行IO等待,形成没必要要的时间浪费,而开启多线程能在线程A等待时,自动切换到线程B,能够不浪费CPU的资源,从而能提高程序执行效率)。在实际的数据采集过程当中,既考虑网速和响应的问题,也须要考虑自身机器的硬件状况,来设置多进程或多线程
面对海量待抓取网页,只有采用分布式架构,才有可能在较短期内完成一轮抓取工做。
它的开发效率是比较快并且简单的。
爬虫下载慢主要缘由是阻塞等待发往网站的请求和网站返回
1,采用异步与多线程,扩大电脑的cpu利用率; 2,采用消息队列模式 3,提升带宽
Robots协议(也称为爬虫协议、爬虫规则、机器人协议等)也就是robots.txt,网站经过robots协议告诉搜索引擎哪些页面能够抓取,哪些页面不能抓取。
Robots协议是网站国际互联网界通行的道德规范,其目的是保护网站数据和敏感信息、确保用户我的信息和隐私不被侵犯。因其不是命令,故须要搜索引擎自觉遵照。
''' 遇到问题没人解答?小编建立了一个Python学习交流QQ群:857662006 寻找有志同道合的小伙伴, 互帮互助,群里还有不错的视频学习教程和PDF电子书! ''' def get_lines(): with open('file.txt','rb') as f: return f.readlines() if __name__ == '__main__': for e in get_lines(): process(e) # 处理每一行数据
如今要处理一个大小为10G的文件,可是内存只有4G,若是在只修改get_lines 函数而其余代码保持不变的状况下,应该如何实现?须要考虑的问题都有那些?
def get_lines(): with open('file.txt','rb') as f: for i in f: yield i
Pandaaaa906提供的方法
from mmap import mmap def get_lines(fp): with open(fp,"r+") as f: m = mmap(f.fileno(), 0) tmp = 0 for i, char in enumerate(m): if char==b"\n": yield m[tmp:i+1].decode() tmp = i+1 if __name__=="__main__": for i in get_lines("fp_some_huge_file"): print(i)
要考虑的问题有:内存只有4G没法一次性读入10G文件,须要分批读入分批读入数据要记录每次读入数据的位置。分批每次读取数据的大小,过小会在读取操做花费过多时间。
https://stackoverflow.com/questions/30294146/python-fastest-way-to-process-large-file
def print_directory_contents(sPath): """ 这个函数接收文件夹的名称做为输入参数 返回该文件夹中文件的路径 以及其包含文件夹中文件的路径 遇到问题没人解答? 小编建立了一个Python学习交流QQ群:857662006 寻找有志同道合的小伙伴, 互帮互助,群里还有不错的视频学习教程和PDF电子书! """ import os for s_child in os.listdir(s_path): s_child_path = os.path.join(s_path, s_child) if os.path.isdir(s_child_path): print_directory_contents(s_child_path) else: print(s_child_path)
import datetime def dayofyear(): year = input("请输入年份: ") month = input("请输入月份: ") day = input("请输入天: ") date1 = datetime.date(year=int(year),month=int(month),day=int(day)) date2 = datetime.date(year=int(year),month=1,day=1) return (date1-date2).days+1
import random alist = [1,2,3,4,5] random.shuffle(alist) print(alist)
sorted(d.items(),key=lambda x:x[1])
d = {key:value for (key,value) in iterable}
print("aStr"[::-1])
str1 = "k:1|k1:2|k2:3|k3:4" def str2dict(str1): dict1 = {} for iterms in str1.split('|'): key,value = iterms.split(':') dict1[key] = value return dict1 #字典推导式 d = {k:int(v) for t in str1.split("|") for k, v in (t.split(":"), )}
alist = [{'name':'a','age':20},{'name':'b','age':30},{'name':'c','age':25}] def sort_by_age(list1): return sorted(alist,key=lambda x:x['age'],reverse=True)
list = ['a','b','c','d','e'] print(list[10:])
代码将输出[],不会产生IndexError错误,就像所指望的那样,尝试用超出成员的个数的index来获取某个列表的成员。例如,尝试获取list[10]和以后的成员,会致使IndexError。然而,尝试获取列表的切片,开始的index超过了成员个数不会产生IndexError,而是仅仅返回一个空列表。这成为特别让人恶心的疑难杂症,由于运行的时候没有错误产生,致使Bug很难被追踪到。
print([x*11 for x in range(10)])
list1 = [1,2,3] list2 = [3,4,5] set1 = set(list1) set2 = set(list2) print(set1 & set2) print(set1 ^ set2)
l1 = ['b','c','d','c','a','a'] l2 = list(set(l1)) print(l2)
用list类的sort方法:
l1 = ['b','c','d','c','a','a'] l2 = list(set(l1)) l2.sort(key=l1.index) print(l2)
也能够这样写:
l1 = ['b','c','d','c','a','a'] l2 = sorted(set(l1),key=l1.index) print(l2)
也能够用遍历:
''' 遇到问题没人解答?小编建立了一个Python学习交流QQ群:857662006 寻找有志同道合的小伙伴, 互帮互助,群里还有不错的视频学习教程和PDF电子书! ''' l1 = ['b','c','d','c','a','a'] l2 = [] for i in l1: if not i in l2: l2.append(i) print(l2)
A,B 中相同元素:print(set(A)&set(B)) A,B 中不一样元素: print(set(A)^set(B))
a. 在python里凡是继承了object的类,都是新式类
b. Python3里只有新式类
c. Python2里面继承object的是新式类,没有写父类的是经典类
d. 经典类目前在Python里基本没有应用
a. 整型 int、 长整型 long、浮点型 float、 复数 complex
b. 字符串 str、 列表 list、 元祖 tuple
c. 字典 dict 、 集合 set
d. Python3 中没有 long,只有无限精度的 int
第一种方法:使用装饰器
''' 遇到问题没人解答?小编建立了一个Python学习交流QQ群:857662006 寻找有志同道合的小伙伴, 互帮互助,群里还有不错的视频学习教程和PDF电子书! ''' def singleton(cls): instances = {} def wrapper(*args, **kwargs): if cls not in instances: instances[cls] = cls(*args, **kwargs) return instances[cls] return wrapper @singleton class Foo(object): pass foo1 = Foo() foo2 = Foo() print(foo1 is foo2) # True
第二种方法:使用基类
New 是真正建立实例对象的方法,因此重写基类的new 方法,以此保证建立对象的时候只生成一个实例
class Singleton(object): def __new__(cls, *args, **kwargs): if not hasattr(cls, '_instance'): cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs) return cls._instance class Foo(Singleton): pass foo1 = Foo() foo2 = Foo() print(foo1 is foo2) # True
第三种方法:元类,元类是用于建立类对象的类,类对象建立实例对象时必定要调用call方法,所以在调用call时候保证始终只建立一个实例便可,type是python的元类
''' 遇到问题没人解答?小编建立了一个Python学习交流QQ群:857662006 寻找有志同道合的小伙伴, 互帮互助,群里还有不错的视频学习教程和PDF电子书! ''' class Singleton(type): def __call__(cls, *args, **kwargs): if not hasattr(cls, '_instance'): cls._instance = super(Singleton, cls).__call__(*args, **kwargs) return cls._instance # Python2 class Foo(object): __metaclass__ = Singleton # Python3 class Foo(metaclass=Singleton): pass foo1 = Foo() foo2 = Foo() print(foo1 is foo2) # True
class Solution(object): def reverse(self,x): if -10<x<10: return x str_x = str(x) if str_x[0] !="-": str_x = str_x[::-1] x = int(str_x) else: str_x = str_x[1:][::-1] x = int(str_x) x = -x return x if -2147483648<x<2147483647 else 0 if __name__ == '__main__': s = Solution() reverse_int = s.reverse(-120) print(reverse_int)
第一种方法:
import os def get_files(dir,suffix): res = [] for root,dirs,files in os.walk(dir): for filename in files: name,suf = os.path.splitext(filename) if suf == suffix: res.append(os.path.join(root,filename)) print(res) get_files("./",'.pyc')
第二种方法:
import os def pick(obj): if ob.endswith(".pyc"): print(obj) def scan_path(ph): file_list = os.listdir(ph) for obj in file_list: if os.path.isfile(obj): pick(obj) elif os.path.isdir(obj): scan_path(obj) if __name__=='__main__': path = input('输入目录') scan_path(path)
第三种方法
''' 遇到问题没人解答?小编建立了一个Python学习交流QQ群:857662006 寻找有志同道合的小伙伴, 互帮互助,群里还有不错的视频学习教程和PDF电子书! ''' from glob import iglob def func(fp, postfix): for i in iglob(f"{fp}/**/*{postfix}", recursive=True): print(i) if __name__ == "__main__": postfix = ".pyc" func("K:\Python_script", postfix)
遍历在新在列表操做,删除时在原来的列表操做
a = [1,2,3,4,5,6,7,8] print(id(a)) print(id(a[:])) for i in a[:]: if i>5: pass else: a.remove(i) print(a) print('-----------') print(id(a)) #filter a=[1,2,3,4,5,6,7,8] b = filter(lambda x: x>5,a) print(list(b))
列表解析
a=[1,2,3,4,5,6,7,8] b = [i for i in a if i>5] print(b)
倒序删除
由于列表老是‘向前移’,因此能够倒序遍历,即便后面的元素被修改了,尚未被遍历的元素和其坐标仍是保持不变的
a=[1,2,3,4,5,6,7,8] print(id(a)) for i in range(len(a)-1,-1,-1): if a[i]>5: pass else: a.remove(a[i]) print(id(a)) print('-----------') print(a)
全字母短句 PANGRAM 是包含全部英文字母的句子,好比:A QUICK BROWN FOX JUMPS OVER THE LAZY DOG. 定义并实现一个方法 get_missing_letter, 传入一个字符串采纳数,返回参数字符串变成一个 PANGRAM 中所缺失的字符。应该忽略传入字符串参数中的大小写,返回应该都是小写字符并按字母顺序排序(请忽略全部非 ACSII 字符)
下面示例是用来解释,双引号不须要考虑:
(0)输入: "A quick brown for jumps over the lazy dog"
返回:""
(1)输入: "A slow yellow fox crawls under the proactive dog"
返回: "bjkmqz"
(2)输入: "Lions, and tigers, and bears, oh my!"
返回: "cfjkpquvwxz"
(3)输入: ""
返回:"abcdefghijklmnopqrstuvwxyz"
''' 遇到问题没人解答?小编建立了一个Python学习交流QQ群:857662006 寻找有志同道合的小伙伴, 互帮互助,群里还有不错的视频学习教程和PDF电子书! ''' def get_missing_letter(a): s1 = set("abcdefghijklmnopqrstuvwxyz") s2 = set(a) ret = "".join(sorted(s1-s2)) return ret print(get_missing_letter("python"))
1,可变类型有list,dict.不可变类型有string,number,tuple.
2,当进行修改操做时,可变类型传递的是内存中的地址,也就是说,直接修改内存中的值,并无开辟新的内存。
3,不可变类型被改变时,并无改变原内存地址中的值,而是开辟一块新的内存,将原地址中的值复制过去,对这块新开辟的内存中的值进行操做。
is:比较的是两个对象的id值是否相等,也就是比较俩对象是否为同一个实例对象。是否指向同一个内存地址
== :比较的两个对象的内容/值是否相等,默认会调用对象的eq()方法
a = [1,2,3,4,5,6,7,8,9,10] res = [ i for i in a if i%2==1] print(res)
from functools import reduce #1.使用sum内置求和函数 num = sum([1,2,3,10248]) print(num) #2.reduce 函数 num1 = reduce(lambda x,y :x+y,[1,2,3,10248]) print(num1)
函数做用域的LEGB顺序
1.什么是LEGB?
L:local 函数内部做用域
E: enclosing 函数内部与内嵌函数之间
G: global 全局做用域
B:build-in 内置做用
python在函数里面的查找分为4种,称之为LEGB,也正是按照这是顺序来查找的
"123"
转换成 123
,不使用内置api,例如 int()
方法一:利用 str
函数
def atoi(s): num = 0 for v in s: for j in range(10): if v == str(j): num = num * 10 + j return num
方法二:利用 ord
函数
def atoi(s): num = 0 for v in s: num = num * 10 + ord(v) - ord('0') return num
方法三: 利用 eval
函数
def atoi(s): num = 0 for v in s: t = "%s * 1" % v n = eval(t) num = num * 10 + n return num
方法四: 结合方法二,使用 reduce
,一行解决
from functools import reduce def atoi(s): return reduce(lambda num, v: num * 10 + ord(v) - ord('0'), s, 0)
给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。你能够假设每一个输入只对应一种答案,且一样的元素不能被重复利用。示例:给定nums = [2,7,11,15],target=9 由于 nums[0]+nums[1] = 2+7 =9,因此返回[0,1]
''' 遇到问题没人解答?小编建立了一个Python学习交流QQ群:857662006 寻找有志同道合的小伙伴, 互帮互助,群里还有不错的视频学习教程和PDF电子书! ''' class Solution: def twoSum(self,nums,target): """ :type nums: List[int] :type target: int :rtype: List[int] """ d = {} size = 0 while size < len(nums): if target-nums[size] in d: if d[target-nums[size]] <size: return [d[target-nums[size]],size] else: d[nums[size]] = size size = size +1 solution = Solution() list = [2,7,11,15] target = 9 nums = solution.twoSum(list,target) print(nums)
给列表中的字典排序:假设有以下list对象,alist=[{"name":"a","age":20},{"name":"b","age":30},{"name":"c","age":25}],将alist中的元素按照age从大到小排序 alist=[{"name":"a","age":20},{"name":"b","age":30},{"name":"c","age":25}]
alist_sort = sorted(alist,key=lambda e: e.__getitem__('age'),reverse=True)
def distFunc1(a): """使用集合去重""" a = list(set(a)) print(a) def distFunc2(a): """将一个列表的数据取出放到另外一个列表中,中间做判断""" list = [] for i in a: if i not in list: list.append(i) #若是须要排序的话用sort list.sort() print(list) def distFunc3(a): """使用字典""" b = {} b = b.fromkeys(a) c = list(b.keys()) print(c) if __name__ == "__main__": a = [1,2,4,2,4,5,7,10,5,5,7,8,9,0,3] distFunc1(a) distFunc2(a) distFunc3(a)
import re # 方法一 def test(filepath): distone = {} with open(filepath) as f: for line in f: line = re.sub("\W+", " ", line) lineone = line.split() for keyone in lineone: if not distone.get(keyone): distone[keyone] = 1 else: distone[keyone] += 1 num_ten = sorted(distone.items(), key=lambda x:x[1], reverse=True)[:10] num_ten =[x[0] for x in num_ten] return num_ten # 方法二 # 使用 built-in 的 Counter 里面的 most_common import re from collections import Counter def test2(filepath): with open(filepath) as f: return list(map(lambda c: c[0], Counter(re.sub("\W+", " ", f.read()).split()).most_common(10)))
该函数的输入是一个仅包含数字的list,输出一个新的list,其中每个元素要知足如下条件:
一、该元素是偶数
二、该元素在原list中是在偶数的位置(index是偶数)
def num_list(num): return [i for i in num if i %2 ==0 and num.index(i)%2==0] num = [0,1,2,3,4,5,6,7,8,9,10] result = num_list(num) print(result)
该列表只包含知足如下条件的值,元素为原始列表中偶数切片
list_data = [1,2,5,8,10,3,18,6,20] res = [x for x in list_data[::2] if x %2 ==0] print(res)
[x * x for x in range(1,11)]
import datetime y = int(input("请输入4位数字的年份:")) m = int(input("请输入月份:")) d = int(input("请输入是哪一天")) targetDay = datetime.date(y,m,d) dayCount = targetDay - datetime.date(targetDay.year -1,12,31) print("%s是 %s年的第%s天。"%(targetDay,y,dayCount.days))
def loop_merge_sort(l1,l2): tmp = [] while len(l1)>0 and len(l2)>0: if l1[0] <l2[0]: tmp.append(l1[0]) del l1[0] else: tmp.append(l2[0]) del l2[0] while len(l1)>0: tmp.append(l1[0]) del l1[0] while len(l2)>0: tmp.append(l2[0]) del l2[0] return tmp
让全部奇数都在偶数前面,并且奇数升序排列,偶数降序排序,如字符串'1982376455',变成'1355798642'
# 方法一 def func1(l): if isinstance(l, str): l = [int(i) for i in l] l.sort(reverse=True) for i in range(len(l)): if l[i] % 2 > 0: l.insert(0, l.pop(i)) print(''.join(str(e) for e in l)) # 方法二 def func2(l): print("".join(sorted(l, key=lambda x: int(x) % 2 == 0 and 20 - int(x) or int(x))))
''' 遇到问题没人解答?小编建立了一个Python学习交流QQ群:857662006 寻找有志同道合的小伙伴, 互帮互助,群里还有不错的视频学习教程和PDF电子书! ''' def find_second_large_num(num_list): """ 找出数组第2大的数字 """ # 方法一 # 直接排序,输出倒数第二个数便可 tmp_list = sorted(num_list) print("方法一\nSecond_large_num is :", tmp_list[-2]) # 方法二 # 设置两个标志位一个存储最大数一个存储次大数 # two 存储次大值,one 存储最大值,遍历一次数组便可,先判断是否大于 one,若大于将 one 的值给 two,将 num_list[i] 的值给 one,不然比较是否大于two,若大于直接将 num_list[i] 的值给two,不然pass one = num_list[0] two = num_list[0] for i in range(1, len(num_list)): if num_list[i] > one: two = one one = num_list[i] elif num_list[i] > two: two = num_list[i] print("方法二\nSecond_large_num is :", two) # 方法三 # 用 reduce 与逻辑符号 (and, or) # 基本思路与方法二同样,可是不须要用 if 进行判断。 from functools import reduce num = reduce(lambda ot, x: ot[1] < x and (ot[1], x) or ot[0] < x and (x, ot[1]) or ot, num_list, (0, 0))[0] print("方法三\nSecond_large_num is :", num) if __name__ == '__main___': num_list = [34, 11, 23, 56, 78, 0, 9, 12, 3, 7, 5] find_second_large_num(num_list)
def multi(): return [lambda x : i*x for i in range(4)] print([m(3) for m in multi()])
正确答案是[9,9,9,9],而不是[0,3,6,9]产生的缘由是Python的闭包的后期绑定致使的,这意味着在闭包中的变量是在内部函数被调用的时候被查找的,由于,最后函数被调用的时候,for循环已经完成, i 的值最后是3,所以每个返回值的i都是3,因此最后的结果是[9,9,9,9]
# 方法一 def count_str(str_data): """定义一个字符出现次数的函数""" dict_str = {} for i in str_data: dict_str[i] = dict_str.get(i, 0) + 1 return dict_str dict_str = count_str("AAABBCCAC") str_count_data = "" for k, v in dict_str.items(): str_count_data += k + str(v) print(str_count_data) # 方法二 from collections import Counter print("".join(map(lambda x: x[0] + str(x[1]), Counter("AAABBCCAC").most_common())))
类方法: 是类对象的方法,在定义时须要在上方使用 @classmethod 进行装饰,形参为cls,表示类对象,类对象和实例对象均可调用
类实例方法: 是类实例化对象的方法,只有实例对象能够调用,形参为self,指代对象自己;
静态方法: 是一个任意函数,在其上方使用 @staticmethod 进行装饰,能够用对象直接调用,静态方法实际上跟该类没有太大关系
class Car: def __init__(self,name,loss): # loss [价格,油耗,千米数] self.name = name self.loss = loss def getName(self): return self.name def getPrice(self): # 获取汽车价格 return self.loss[0] def getLoss(self): # 获取汽车损耗值 return self.loss[1] * self.loss[2] Bmw = Car("宝马",[60,9,500]) # 实例化一个宝马车对象 print(getattr(Bmw,"name")) # 使用getattr()传入对象名字,属性值。 print(dir(Bmw)) # 获Bmw全部的属性和方法
class Array: __list = [] def __init__(self): print "constructor" def __del__(self): print "destruct" def __str__(self): return "this self-defined array class" def __getitem__(self,key): return self.__list[key] def __len__(self): return len(self.__list) def Add(self,value): self.__list.append(value) def Remove(self,index): del self.__list[index] def DisplayItems(self): print "show all items---" for item in self.__list: print item
A,变量没必要事先声明 B,变量无须先建立和赋值而直接使用
C,变量无须指定类型 D,可使用del释放资源
内存管理机制: 引用计数、垃圾回收、内存池
引用计数:引用计数是一种很是高效的内存管理手段,当一个Python对象被引用时其引用计数增长1,
当其再也不被一个变量引用时则计数减1,当引用计数等于0时对象被删除。弱引用不会增长引用计数
垃圾回收:
1.引用计数
引用计数也是一种垃圾收集机制,并且也是一种最直观、最简单的垃圾收集技术。当Python的某个对象的引用计数降为0时,说明没有任何引用指向该对象,该对象就成为要被回收的垃圾了。好比某个新建对象,它被分配给某个引用,对象的引用计数变为1,若是引用被删除,对象的引用计数为0,那么该对象就能够被垃圾回收。不过若是出现循环引用的话,引用计数机制就再也不起有效的做用了。
2.标记清除
调优手段
1.手动垃圾回收
2.调高垃圾回收阈值
3.避免循环引用
内存泄漏指因为疏忽或错误形成程序未能释放已经再也不使用的内存。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,致使在释放该段内存以前就失去了对该段内存的控制,从而形成了内存的浪费。
有__del__()
函数的对象间的循环引用是致使内存泄露的主凶。不使用一个对象时使用: del object 来删除一个对象的引用计数就能够有效防止内存泄露问题。
经过Python扩展模块gc 来查看不能回收的对象的详细信息。
能够经过 sys.getrefcount(obj) 来获取对象的引用计数,并根据返回值是否为0来判断是否内存泄露
[表达式 for 变量 in 列表] 或者 [表达式 for 变量 in 列表 if 条件]
read 读取整个文件
readline 读取下一行
readlines 读取整个文件到一个迭代器以供咱们遍历
散列函数(英语:Hash function)又称散列算法、哈希函数,是一种从任何一种数据中建立小的数字“指纹”的方法。散列函数把消息或数据压缩成摘要,使得数据量变小,将数据的格式固定下来。该函数将数据打乱混合,从新建立一个叫作散列值(hash values,hash codes,hash sums,或hashes)的指纹。散列值一般用一个短的随机字母和数字组成的字符串来表明
函数重载主要是为了解决两个问题。
1。可变参数类型。
2。可变参数个数。
另外,一个基本的设计原则是,仅仅当两个函数除了参数类型和参数个数不一样之外,其功能是彻底相同的,此时才使用函数重载,若是两个函数的功能其实不一样,那么不该当使用重载,而应当使用一个名字不一样的函数。
好吧,那么对于状况 1 ,函数功能相同,可是参数类型不一样,python 如何处理?答案是根本不须要处理,由于 python 能够接受任何类型的参数,若是函数的功能相同,那么不一样的参数类型在 python 中极可能是相同的代码,没有必要作成两个不一样函数。
那么对于状况 2 ,函数功能相同,但参数个数不一样,python 如何处理?你们知道,答案就是缺省参数。对那些缺乏的参数设定为缺省参数便可解决问题。由于你假设函数功能相同,那么那些缺乏的参数终归是须要用的。
好了,鉴于状况 1 跟 状况 2 都有了解决方案,python 天然就不须要函数重载了。
''' 遇到问题没人解答?小编建立了一个Python学习交流QQ群:857662006 寻找有志同道合的小伙伴, 互帮互助,群里还有不错的视频学习教程和PDF电子书! ''' import datetime class TimeException(Exception): def __init__(self, exception_info): super().__init__() self.info = exception_info def __str__(self): return self.info def timecheck(func): def wrapper(*args, **kwargs): if datetime.datetime.now().year == 2019: func(*args, **kwargs) else: raise TimeException("函数已过期") return wrapper @timecheck def test(name): print("Hello {}, 2019 Happy".format(name)) if __name__ == "__main__": test("backbp")
list(filter(lambda x: x % 2 == 0, range(10)))
1.函数设计要尽可能短小
2.函数声明要作到合理、简单、易于使用
3.函数参数设计应该考虑向下兼容
4.一个函数只作一件事情,尽可能保证函数语句粒度的一致性
Python的参数传递有:位置参数、默认参数、可变参数、关键字参数。
函数的传值究竟是值传递仍是引用传递、要分状况:
不可变参数用值传递:像整数和字符串这样的不可变对象,是经过拷贝进行传递的,由于你不管如何都不可能在原处改变不可变对象。
可变参数是引用传递:好比像列表,字典这样的对象是经过引用传递、和C语言里面的用指针传递数组很类似,可变对象能在函数内部改变。
globals() # 返回包含当前做用余全局变量的字典。 global 变量 设置使用全局变量
缺省参数指在调用函数的时候没有传入参数的状况下,调用默认的参数,在调用函数的同时赋值时,所传入的参数会替代默认参数。
*args是不定长参数,它能够表示输入参数是不肯定的,能够是任意多个。
**kwargs是关键字参数,赋值的时候是以键值对的方式,参数能够是任意多对在定义函数的时候
不肯定会有多少参数会传入时,就可使用两个参数
带定长参数的装饰器
def new_func(func): def wrappedfun(username, passwd): if username == 'root' and passwd == '123456789': print('经过认证') print('开始执行附加功能') return func() else: print('用户名或密码错误') return return wrappedfun @new_func def origin(): print('开始执行函数') origin('root','123456789')
带不定长参数的装饰器
def new_func(func): def wrappedfun(*parts): if parts: counts = len(parts) print('本系统包含 ', end='') for part in parts: print(part, ' ',end='') print('等', counts, '部分') return func() else: print('用户名或密码错误') return func() return wrappedfun
Python中一切皆对象,函数名是函数在内存中的空间,也是一个对象
在编写代码时只写框架思路,具体实现还未编写就能够用pass进行占位,是程序不报错,不会进行任何操做。
a = 10 b = 20 c = [a] a = 15
答:10对于字符串,数字,传递是相应的值
a, b = b, a
map(lambda x: x * x, [1, 2, 3, 4]) # 使用 lambda # [1, 4, 9, 16] reduce(lambda x, y: x * y, [1, 2, 3, 4]) # 至关于 ((1 * 2) * 3) * 4 # 24
回调函数是把函数的指针(地址)做为参数传递给另外一个函数,将整个函数看成一个对象,赋值给调用的函数。
内建类型:布尔类型,数字,字符串,列表,元组,字典,集合
输出字符串'a'的内建方法
[0, 1, 4]
hasattr(object,name)函数:
判断一个对象里面是否有name属性或者name方法,返回bool值,有name属性(方法)返回True,不然返回False。
''' 遇到问题没人解答?小编建立了一个Python学习交流QQ群:857662006 寻找有志同道合的小伙伴, 互帮互助,群里还有不错的视频学习教程和PDF电子书! ''' class function_demo(object): name = 'demo' def run(self): return "hello function" functiondemo = function_demo() res = hasattr(functiondemo, "name") # 判断对象是否有name属性,True res = hasattr(functiondemo, "run") # 判断对象是否有run方法,True res = hasattr(functiondemo, "age") # 判断对象是否有age属性,False print(res)
getattr(object, name[,default])函数:
获取对象object的属性或者方法,若是存在则打印出来,若是不存在,打印默认值,默认值可选。注意:若是返回的是对象的方法,则打印结果是:方法的内存地址,若是须要运行这个方法,能够在后面添加括号().
functiondemo = function_demo() getattr(functiondemo, "name")# 获取name属性,存在就打印出来 --- demo getattr(functiondemo, "run") # 获取run 方法,存在打印出方法的内存地址 getattr(functiondemo, "age") # 获取不存在的属性,报错 getattr(functiondemo, "age", 18)# 获取不存在的属性,返回一个默认值
setattr(object, name, values)函数:
给对象的属性赋值,若属性不存在,先建立再赋值
class function_demo(object): name = "demo" def run(self): return "hello function" functiondemo = function_demo() res = hasattr(functiondemo, "age") # 判断age属性是否存在,False print(res) setattr(functiondemo, "age", 18) # 对age属性进行赋值,无返回值 res1 = hasattr(functiondemo, "age") # 再次判断属性是否存在,True
综合使用
class function_demo(object): name = "demo" def run(self): return "hello function" functiondemo = function_demo() res = hasattr(functiondemo, "addr") # 先判断是否存在 if res: addr = getattr(functiondemo, "addr") print(addr) else: addr = getattr(functiondemo, "addr", setattr(functiondemo, "addr", "北京首都")) print(addr)
reduce(lambda x,y : x*y,range(1,n+1))
设计模式是通过总结,优化的,对咱们常常会碰到的一些编程问题的可重用解决方案。一个设计模式并不像一个类或一个库那样可以直接做用于咱们的代码,反之,设计模式更为高级,它是一种必须在特定情形下实现的一种方法模板。
常见的是工厂模式和单例模式
#python2 class A(object): __instance = None def __new__(cls,*args,**kwargs): if cls.__instance is None: cls.__instance = objecet.__new__(cls) return cls.__instance else: return cls.__instance
单例模式应用的场景通常发如今如下条件下:
资源共享的状况下,避免因为资源操做时致使的性能或损耗等,如日志文件,应用配置。
控制资源的状况下,方便资源之间的互相通讯。如线程池等,1,网站的计数器 2,应用配置 3.多线程池 4数据库配置 数据库链接池 5.应用程序的日志应用…
print([x*x for x in range(1, 11)])
装饰器本质上是一个callable object ,它可让其余函数在不须要作任何代码变更的前提下增长额外功能,装饰器的返回值也是一个函数对象。
''' 遇到问题没人解答?小编建立了一个Python学习交流QQ群:857662006 寻找有志同道合的小伙伴, 互帮互助,群里还有不错的视频学习教程和PDF电子书! ''' import time from functools import wraps def timeit(func): @wraps(func) def wrapper(*args, **kwargs): start = time.clock() ret = func(*args, **kwargs) end = time.clock() print('used:',end-start) return ret return wrapper @timeit def foo(): print('in foo()'foo())
在函数内部再定义一个函数,而且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包。
装饰器本质上是一个callable object,它能够在让其余函数在不须要作任何代码的变更的前提下增长额外的功能。装饰器的返回值也是一个函数的对象,它常常用于有切面需求的场景。好比:插入日志,性能测试,事务处理,缓存。权限的校验等场景,有了装饰器就能够抽离出大量的与函数功能自己无关的雷同代码并发并继续使用。
详细参考:https://manjusaka.itscoder.com/2018/02/23/something-about-decorator/
迭代器是遵循迭代协议的对象。用户可使用 iter() 以从任何序列获得迭代器(如 list, tuple, dictionary, set 等)。另外一个方法则是建立一个另外一种形式的迭代器 —— generator 。要获取下一个元素,则使用成员函数 next()(Python 2)或函数 next() function (Python 3) 。当没有元素时,则引起 StopIteration 此例外。若要实现本身的迭代器,则只要实现 next()(Python 2)或 __next__
()( Python 3)
生成器(Generator),只是在须要返回数据的时候使用yield语句。每次next()被调用时,生成器会返回它脱离的位置(它记忆语句最后一次执行的位置和全部的数据值)
区别:生成器能作到迭代器能作的全部事,并且由于自动建立iter()和next()方法,生成器显得特别简洁,并且生成器也是高效的,使用生成器表达式取代列表解析能够同时节省内存。除了建立和保存程序状态的自动方法,当发生器终结时,还会自动抛出StopIteration异常。
X= (i for i in range(10))
X是 generator类型
N =100 print ([[x for x in range(1,100)] [i:i+3] for i in range(0,100,3)])
yield就是保存当前程序执行状态。你用for循环的时候,每次取一个元素的时候就会计算一次。用yield的函数叫generator,和iterator同样,它的好处是不用一次计算全部元素,而是用一次算一次,能够节省不少空间,generator每次计算须要上一次计算结果,因此用yield,不然一return,上次计算结果就没了