python 切片_全面解讀Python高級特性切片

e2fb38293346e92ff7e20fae31129713.png


大家好,歡迎來到Crossin的編程教室!

眾所周知,我們可以通過索引值(或稱下標)來查找序列類型(如字符串、列表、元組…)中的單個元素,那么,如果要獲取一個索引區間的元素該怎么辦呢?

切片(slice)就是一種截取索引片段的技術,借助切片技術,我們可以十分靈活地處理序列類型的對象。通常來說,切片的作用就是截取序列對象,然而,對于非序列對象,我們是否有辦法做到切片操作呢?在使用切片的過程中,有什么要點值得重視,又有什么底層原理值得關注呢?本文將主要跟大家一起來探討這些內容,希望我能與你共同學習進步。

1、切片的基礎用法

列表是 Python 中極為基礎且重要的一種數據結構,也是最能發揮切片的用處的一種數據結構,所以在前兩節,我將以列表為例介紹切片的一些常見用法。

首先是切片的書寫形式:[i : i+n : m] ;其中,i 是切片的起始索引值,為列表首位時可省略;i+n 是切片的結束位置,為列表末位時可省略;m 可以不提供,默認值是1,不允許為0 ,當m為負數時,列表翻轉。注意:這些值都可以大于列表長度,不會報越界。

切片的基本含義是:從序列的第i位索引起,向右取到后n位元素為止,按m間隔過濾

li?=?[1,?4,?5,?6,?7,?9,?11,?14,?16]

#?以下寫法都可以表示整個列表,其中?X?>=?len(li)
li[0:X]?==?li[0:]?==?li[:X]?==?li[:]?
==?li[::]?==?li[-X:X]?==?li[-X:]

li[1:5]?==?[4,5,6,7]?#?從1起,取5-1位元素
li[1:5:2]?==?[4,6]?#?從1起,取5-1位元素,按2間隔過濾
li[-1:]?==?[16]?#?取倒數第一個元素
li[-4:-2]?==?[9,?11]?#?從倒數第四起,取-2-(-4)=2位元素
li[:-2]?==?li[-len(li):-2]?
==?[1,4,5,6,7,9,11]?#?從頭開始,取-2-(-len(li))=7位元素

#?步長為負數時,列表先翻轉,再截取
li[::-1]?==?[16,14,11,9,7,6,5,4,1]?#?翻轉整個列表
li[::-2]?==?[16,11,7,5,1]?#?翻轉整個列表,再按2間隔過濾
li[:-5:-1]?==?[16,14,11,9]?#?翻轉整個列表,取-5-(-len(li))=4位元素
li[:-5:-3]?==?[16,9]?#?翻轉整個列表,取-5-(-len(li))=4位元素,再按3間隔過濾

#?切片的步長不可以為0
li[::0]??#?報錯(ValueError:?slice?step?cannot?be?zero)

上述的某些例子對于初學者(甚至很多老手)來說,可能還不好理解,但是它們都離不開切片的基本語法,所以為方便起見,我將它們也歸入基礎用法中。

對于這些樣例,我個人總結出兩條經驗:

(1)牢牢記住公式[i : i+n : m],當出現缺省值時,通過想象把公式補全;

(2)索引為負且步長為正時,按倒數計算索引位置;索引為負且步長為負時,先翻轉列表,再按倒數計算索引位置。

2、切片的高級用法

一般而言,切片操作的返回結果是一個新的獨立的序列。以列表為例,列表切片后得到的還是一個列表,占用新的內存地址。

當取出切片的結果時,它是一個獨立對象,因此,可以將其用于賦值操作,也可以用于其它傳遞值的場景。但是,切片只是淺拷貝 ,它拷貝的是原列表中元素的引用,所以,當存在變長對象的元素時,新列表將受制于原列表。

li?=?[1,?2,?3,?4]
ls?=?li[::]

li?==?ls?#?True
id(li)?==?id(ls)?#?False
li.append(li[2:4])?#?[1,?2,?3,?4,?[3,?4]]
ls.extend(ls[2:4])?#?[1,?2,?3,?4,?3,?4]

#?下例等價于判斷li長度是否大于8
if(li[8:]):
????print("not?empty")
else:
????print("empty")

#?切片列表受制于原列表
lo?=?[1,[1,1],2,3]
lp?=?lo[:2]?#?[1,?[1,?1]]
lo[1].append(1)?#?[1,?[1,?1,?1],?2,?3]
lp?#?[1,?[1,?1,?1]]

由于可見,將切片結果取出,它可以作為獨立對象使用,但是也要注意,是否取出了變長對象的元素。

切片既可以作為獨立對象被“取出”原序列,也可以留在原序列,作為一種占位符使用。

不久前,我介紹了幾種拼接字符串的方法,其中三種格式化類的拼接方法(即 %、format()、template)就是使用了占位符的思想。對于列表來說,使用切片作為占位符,同樣能夠實現拼接列表的效果。特別需要注意的是,給切片賦值的必須是可迭代對象。

li?=?[1,?2,?3,?4]

#?在頭部拼接
li[:0]?=?[0]?#?[0,?1,?2,?3,?4]
#?在末尾拼接
li[len(li):]?=?[5,7]?#?[0,?1,?2,?3,?4,?5,?7]
#?在中部拼接
li[6:6]?=?[6]?#?[0,?1,?2,?3,?4,?5,?6,?7]

#?給切片賦值的必須是可迭代對象
li[-1:-1]?=?6?#?(報錯,TypeError:?can?only?assign?an?iterable)
li[:0]?=?(9,)?#??[9,?0,?1,?2,?3,?4,?5,?6,?7]
li[:0]?=?range(3)?#??[0,?1,?2,?9,?0,?1,?2,?3,?4,?5,?6,?7]

上述例子中,若將切片作為獨立對象取出,那你會發現它們都是空列表,即 li[:0]==li[len(li):]==li[6:6]==[] ,我將這種占位符稱為“純占位符”,對純占位符賦值,并不會破壞原有的元素,只會在特定的索引位置中拼接進新的元素。刪除純占位符時,也不會影響列表中的元素。

與“純占位符”相對應,“非純占位符”的切片是非空列表,對它進行操作(賦值與刪除),將會影響原始列表。如果說純占位符可以實現列表的拼接,那么,非純占位符可以實現列表的替換。

li?=?[1,?2,?3,?4]

#?不同位置的替換
li[:3]?=?[7,8,9]?#?[7,?8,?9,?4]
li[3:]?=?[5,6,7]?#?[7,?8,?9,?5,?6,?7]
li[2:4]?=?['a','b']?#?[7,?8,?'a',?'b',?6,?7]

#?非等長替換
li[2:4]?=?[1,2,3,4]?#?[7,?8,?1,?2,?3,?4,?6,?7]
li[2:6]?=?['a']??#?[7,?8,?'a',?6,?7]

#?刪除元素
del?li[2:3]?#?[7,?8,?6,?7]

切片占位符可以帶步長,從而實現連續跨越性的替換或刪除效果。需要注意的是,這種用法只支持等長替換。

li?=?[1,?2,?3,?4,?5,?6]

li[::2]?=?['a','b','c']?#?['a',?2,?'b',?4,?'c',?6]
li[::2]?=?[0]*3?#?[0,?2,?0,?4,?0,?6]
li[::2]?=?['w']?#?報錯,attempt?to?assign?sequence?of?size?1?to?extended?slice?of?size?3

del?li[::2]?#?[2,?4,?6]

3、自定義對象實現切片功能

切片是 Python 中最迷人最強大最 Amazing 的語言特性(幾乎沒有之一),以上兩小節雖然介紹了切片的基礎用法與高級用法,但這些還不足以充分地展露切片的魅力,所以,在接下來的兩章節中,我們將聚焦于它的更高級用法。

前兩節內容都是基于原生的序列類型(如字符串、列表、元組……),那么,我們是否可以定義自己的序列類型并讓它支持切片語法呢?更進一步,我們是否可以自定義其它對象(如字典)并讓它支持切片呢?

3.1、魔術方法:`getitem()`

想要使自定義對象支持切片語法并不難,只需要在定義類的時候給它實現魔術方法 __getitem__() 即可。所以,這里就先介紹一下這個方法。

語法:object.__getitem__(self, key)

官方文檔釋義:Called to implement evaluation of self[key]. For sequence types, the accepted keys should be integers and slice objects. Note that the special interpretation of negative indexes (if the class wishes to emulate a sequence type) is up to the __getitem__() method. If key is of an inappropriate type, TypeError may be raised; if of a value outside the set of indexes for the sequence (after any special interpretation of negative values), IndexError should be raised. For mapping types, if key is missing (not in the container), KeyError should be raised.

概括翻譯一下:__getitem__() 方法用于返回參數 key 所對應的值,這個 key 可以是整型數值和切片對象,并且支持負數索引;如果 key 不是以上兩種類型,就會拋 TypeError;如果索引越界,會拋 IndexError ;如果定義的是映射類型,當 key 參數不是其對象的鍵值時,則會拋 KeyError 。

3.2、自定義序列實現切片功能

接下來,我們定義一個簡單的 MyList ,并給它加上切片功能。(PS:僅作演示,不保證其它功能的完備性)。

import?numbers

class?MyList():
????def?__init__(self,?anylist):
????????self.data?=?anylist
????def?__len__(self):
????????return?len(self.data)
????def?__getitem__(self,?index):
????????print("key?is?:?"?+?str(index))
????????cls?=?type(self)
????????if?isinstance(index,?slice):
????????????print("data?is?:?"?+?str(self.data[index]))
????????????return?cls(self.data[index])
????????elif?isinstance(index,?numbers.Integral):
????????????return?self.data[index]
????????else:
????????????msg?=?"{cls.__name__}?indices?must?be?integers"
????????????raise?TypeError(msg.format(cls=cls))

l?=?MyList(["My",?"name",?"is",?"Python貓"])

###?輸出結果:
key?is?:?3
Python貓
key?is?:?slice(None,?2,?None)
data?is?:?['My',?'name']
<__main__.mylist>0x0000019CD83A7A90>
key?is?:?hi
Traceback?(most?recent?call?last):
...
TypeError:?MyList?indices?must?be?integers?or?slices

從輸出結果來看,自定義的 MyList 既支持按索引查找,也支持切片操作,這正是我們的目的。

3.3、自定義字典實現切片功能

切片是序列類型的特性,所以在上例中,我們不需要寫切片的具體實現邏輯。但是,對于其它非序列類型的自定義對象,就得自己實現切片邏輯。以自定義字典為例(PS:僅作演示,不保證其它功能的完備性):

class?MyDict():
????def?__init__(self):
????????self.data?=?{}
????def?__len__(self):
????????return?len(self.data)
????def?append(self,?item):
????????self.data[len(self)]?=?item
????def?__getitem__(self,?key):
????????if?isinstance(key,?int):
????????????return?self.data[key]
????????if?isinstance(key,?slice):
????????????slicedkeys?=?list(self.data.keys())[key]
????????????return?{k:?self.data[k]?for?k?in?slicedkeys}
????????else:
????????????raise?TypeError

d?=?MyDict()
d.append("My")
d.append("name")
d.append("is")
d.append("Python貓")
print(d[2])
print(d[:2])
print(d[-4:-2])
print(d['hi'])

###?輸出結果:
is
{0:?'My',?1:?'name'}
{0:?'My',?1:?'name'}
Traceback?(most?recent?call?last):
...
TypeError

上例的關鍵點在于將字典的鍵值取出,并對鍵值的列表做切片處理,其妙處在于,不用擔心索引越界和負數索引,將字典切片轉換成了字典鍵值的切片,最終實現目的。

4、迭代器實現切片功能

好了,介紹完一般的自定義對象如何實現切片功能,這里將迎來另一類非同一般的對象。

迭代器是 Python 中獨特的一種高級對象,它本身不具備切片功能,然而若能將它用于切片,這便仿佛是錦上添花,能達到如虎添翼的效果。所以,本節將隆重地介紹迭代器如何實現切片功能。

4.1、迭代與迭代器

首先,有幾個基本概念要澄清:迭代、可迭代對象、迭代器。

迭代 是一種遍歷容器類型對象(例如字符串、列表、字典等等)的方式,例如,我們說迭代一個字符串“abc”,指的就是從左往右依次地、逐個地取出它的全部字符的過程。(PS:漢語中迭代一詞有循環反復、層層遞進的意思,但 Python 中此詞要理解成單向水平線性 的,如果你不熟悉它,我建議直接將其理解為遍歷。)

那么,怎么寫出迭代操作的指令呢?最通用的書寫語法就是 for 循環。

#?for循環實現迭代過程
for?char?in?"abc":
????print(char,?end="?")
#?輸出結果:a b c

for 循環可以實現迭代的過程,但是,并非所有對象都可以用于 for 循環,例如,上例中若將字符串“abc”換成任意整型數字,則會報錯:'int' object is not iterable .

這句報錯中的單詞“iterable”指的是“可迭代的”,即 int 類型不是可迭代的。而字符串(string)類型是可迭代的,同樣地,列表、元組、字典等類型,都是可迭代的。

那怎么判斷一個對象是否可迭代呢?為什么它們是可迭代的呢?怎么讓一個對象可迭代呢?

要使一個對象可迭代,就要實現可迭代協議,即需要實現__iter__() 魔術方法,換言之,只要實現了這個魔術方法的對象都是可迭代對象。

那怎么判斷一個對象是否實現了這個方法呢?除了上述的 for 循環外,我還知道四種方法:

#?方法1:dir()查看__iter__
dir(2)?????#?沒有,略
dir("abc")?#?有,略

#?方法2:isinstance()判斷
import?collections
isinstance(2,?collections.Iterable)?????#?False
isinstance("abc",?collections.Iterable)?#?True

#?方法3:hasattr()判斷
hasattr(2,"__iter__")?????#?False
hasattr("abc","__iter__")?#?True

#?方法4:用iter()查看是否報錯
iter(2)?????#?報錯:'int' object is not iterable
iter("abc")?#?

### PS:判斷是否可迭代,還可以查看是否實現__getitem__,為方便描述,本文從略。

這幾種方法中最值得一提的是 iter() 方法,它是 Python 的內置方法,其作用是將可迭代對象變成迭代器 。這句話可以解析出兩層意思:(1)可迭代對象跟迭代器是兩種東西;(2)可迭代對象能變成迭代器。

實際上,迭代器必然是可迭代對象,但可迭代對象不一定是迭代器。兩者有多大的區別呢?

da512eabfe6015c4f4fc8801b7de5445.png

如上圖藍圈所示,普通可迭代對象與迭代器的最關鍵區別可概括為:一同兩不同 ,所謂“一同”,即兩者都是可迭代的(__iter__),所謂“兩不同”,即可迭代對象在轉化為迭代器后,它會丟失一些屬性(__getitem__),同時也增加一些屬性(__next__)。

首先看看增加的屬性 __next__ , 它是迭代器之所以是迭代器的關鍵,事實上,我們正是把同時實現了 __iter__ 方法 和 __next__ 方法的對象定義為迭代器的。

有了多出來的這個屬性,可迭代對象不需要借助外部的 for 循環語法,就能實現自我的迭代/遍歷過程。我發明了兩個概念來描述這兩種遍歷過程(PS:為了易理解,這里稱遍歷,實際也可稱為迭代):它遍歷 指的是通過外部語法而實現的遍歷,自遍歷 指的是通過自身方法實現的遍歷。

借助這兩個概念,我們說,可迭代對象就是能被“它遍歷”的對象,而迭代器是在此基礎上,還能做到“自遍歷”的對象。

ob1?=?"abc"
ob2?=?iter("abc")
ob3?=?iter("abc")

#?ob1它遍歷
for?i?in?ob1:
????print(i,?end?=?"?")???#?a?b?c
for?i?in?ob1:
????print(i,?end?=?"?")???#?a?b?c
#?ob1自遍歷
ob1.__next__()??#?報錯:?'str' object has no attribute '__next__'

#?ob2它遍歷
for?i?in?ob2:
????print(i,?end?=?"?")???#?a?b?c????
for?i?in?ob2:
????print(i,?end?=?"?")???#?無輸出
#?ob2自遍歷
ob2.__next__()??#?報錯:StopIteration

#?ob3自遍歷
ob3.__next__()??#?a
ob3.__next__()??#?b
ob3.__next__()??#?c
ob3.__next__()??#?報錯:StopIteration

通過上述例子可看出,迭代器的優勢在于支持自遍歷,同時,它的特點是單向非循環的,一旦完成遍歷,再次調用就會報錯。

對此,我想到一個比方:普通可迭代對象就像是子彈匣,它遍歷就是取出子彈,在完成操作后又裝回去,所以可以反復遍歷(即多次調用for循環,返回相同結果);而迭代器就像是裝載了子彈匣且不可拆卸的槍,進行它遍歷或者自遍歷都是發射子彈,這是消耗性的遍歷,是無法復用的(即遍歷會有盡頭)。

寫了這么多,稍微小結一下:迭代是一種遍歷元素的方式,按照實現方式劃分,有外部迭代與內部迭代兩種,支持外部迭代(它遍歷)的對象就是可迭代對象,而同時還支持內部迭代(自遍歷)的對象就是迭代器;按照消費方式劃分,可分為復用型迭代與一次性迭代,普通可迭代對象是復用型的,而迭代器是一次性的。

4.2、迭代器切片

前面提到了“一同兩不同”,最后的不同是,普通可迭代對象在轉化成迭代器的過程中會丟失一些屬性,其中關鍵的屬性是 __getitem__ 。在前一節中,我已經介紹了這個魔術方法,并用它實現了自定義對象的切片特性。

那么問題來了:為啥迭代器不繼承這個屬性呢?

首先,迭代器使用的是消耗型的遍歷,這意味著它充滿不確定性,即其長度與索引鍵值對是動態衰減的,所以很難 get 到它的 item ,也就不再需要 __getitem__ 屬性了。其次,若強行給迭代器加上這個屬性,這并不合理,正所謂強扭的瓜不甜……

由此,新的問題來了:既然會丟失這么重要的屬性(還包括其它未標識的屬性),為什么還要使用迭代器呢?

這個問題的答案在于,迭代器擁有不可替代的強大的有用的功能,使得 Python 要如此設計它。限于篇幅,此處不再展開,后續我會專門填坑此話題。

還沒完,死纏爛打的問題來了:能否令迭代器擁有這個屬性呢,即令迭代器繼續支持切片呢?

hi?=?"歡迎關注公眾號:Python貓"
it?=?iter(hi)

#?普通切片
hi[-7:]?#?Python貓

#?反例:迭代器切片
it[-7:]?#?報錯:'str_iterator' object is not subscriptable

迭代器因為缺少__getitem__ ,因此不能使用普通的切片語法。想要實現切片,無非兩種思路:一是自己造輪子,寫實現的邏輯;二是找到封裝好的輪子。

Python 的 itertools 模塊就是我們要找的輪子,用它提供的方法可輕松實現迭代器切片。

import?itertools

#?例1:簡易迭代器
s?=?iter("123456789")
for?x?in?itertools.islice(s,?2,?6):
????print(x,?end?=?"?")???#?輸出:3 4 5 6
for?x?in?itertools.islice(s,?2,?6):
????print(x,?end?=?"?")???#?輸出:9

#?例2:斐波那契數列迭代器
class?Fib():
????def?__init__(self):
????????self.a,?self.b?=?1,?1

????def?__iter__(self):
????????while?True:
????????????yield?self.a
????????????self.a,?self.b?=?self.b,?self.a?+?self.b
f?=?iter(Fib())
for?x?in?itertools.islice(f,?2,?6):
????print(x,?end?=?"?")??#?輸出:2 3 5 8
for?x?in?itertools.islice(f,?2,?6):
????print(x,?end?=?"?")??#?輸出:34 55 89 144

itertools 模塊的 islice() 方法將迭代器與切片完美結合,終于回答了前面的問題。然而,迭代器切片跟普通切片相比,前者有很多局限性。首先,這個方法不是“純函數”(純函數需遵守“相同輸入得到相同輸出”的原則);其次,它只支持正向切片,且不支持負數索引,這都是由迭代器的損耗性所決定的。

那么,我不禁要問:itertools 模塊的切片方法用了什么實現邏輯呢?下方是官網提供的源碼:

def?islice(iterable,?*args):
????#?islice('ABCDEFG',?2)?-->?A?B
????#?islice('ABCDEFG',?2,?4)?-->?C?D
????#?islice('ABCDEFG',?2,?None)?-->?C?D?E?F?G
????#?islice('ABCDEFG',?0,?None,?2)?-->?A?C?E?G
????s?=?slice(*args)
????#?索引區間是[0,sys.maxsize],默認步長是1
????start,?stop,?step?=?s.start?or?0,?s.stop?or?sys.maxsize,?s.step?or?1
????it?=?iter(range(start,?stop,?step))
????try:
????????nexti?=?next(it)
????except?StopIteration:
????????#?Consume?*iterable*?up?to?the?*start*?position.
????????for?i,?element?in?zip(range(start),?iterable):
????????????pass
????????return
????try:
????????for?i,?element?in?enumerate(iterable):
????????????if?i?==?nexti:
????????????????yield?element
????????????????nexti?=?next(it)
????except?StopIteration:
????????#?Consume?to?*stop*.
????????for?i,?element?in?zip(range(i?+?1,?stop),?iterable):
????????????pass

islice() 方法的索引方向是受限的,但它也提供了一種可能性:即允許你對一個無窮的(在系統支持范圍內)迭代器進行切片的能力。這是迭代器切片最具想象力的用途場景。

除此之外,迭代器切片還有一個很實在的應用場景:讀取文件對象中給定行數范圍的數據。

我們知道,從文件中讀取內容主要有兩種方法(參見之前關于文件讀寫的文章):read() 適合讀取內容較少的情況,或者是需要一次性處理全部內容的情況;而 readlines() 適用性更廣,因為它是迭代地讀取內容,既減少內存壓力,又方便逐行對數據處理。

雖然 readlines() 有迭代讀取的優勢,但它是從頭到尾逐行讀取,若文件有幾千行,而我們只想要讀取少數特定行(例如第1000-1009行),那它還是效率太低了。考慮到文件對象天然就是迭代器 ,我們可以使用迭代器切片先行截取,然后再處理,如此效率將大大地提升。

#?test.txt?文件內容
'''

Python貓
python?is?a?cat.
this?is?the?end.
'''

from?itertools?import?islice
with?open('test.txt','r',encoding='utf-8')?as?f:
????print(hasattr(f,?"__next__"))??#?判斷是否迭代器
????content?=?islice(f,?2,?4)
????for?line?in?content:
????????print(line.strip())
###?輸出結果:
True
python?is?a?cat.
this?is?the?end.

本節內容較多,簡單回顧一下:迭代器是一種特殊的可迭代對象,可用于它遍歷與自遍歷,但遍歷過程是損耗型的,不具備循環復用性,因此,迭代器本身不支持切片操作;通過借助 itertools 模塊,我們能實現迭代器切片,將兩者的優勢相結合,其主要用途在于截取大型迭代器(如無限數列、超大文件等等)的片段,實現精準的處理,從而大大地提升性能與效率。

5、小結

最后總結一下,切片是 Python 的一種高級特性,常用于截取序列類型的元素,但并不局限于此,本文主要介紹了它的基礎用法、高級用法(如占位符用法)、自定義對象切片、以及迭代器切片等使用內容。除此之外,切片還有更廣闊多樣的使用場景,例如 Numpy 的多維切片、內存視圖切片、異步迭代器切片等等,都值得我們去探索一番,今天限于篇幅先告一段落,以后我們慢慢學習之。

作者:豌豆花下貓

來源:Python貓


_往期文章推薦_

淺談鏈表-數據結構的重要根基
6fa8204b87ea8d8e4e058b46455b0d2d.png

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/276589.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/276589.shtml
英文地址,請注明出處:http://en.pswp.cn/news/276589.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

十大Web網站漏洞掃描工具

原文鏈接&#xff1a;http://zhumeng8337797.blog.163.com/blog/static/1007689142012819111054920/ 1. Nikto 這是一個開源的Web服務器掃描程序&#xff0c;它可以對Web服務器的多種項目(包括3500個潛在的危險文件/CGI&#xff0c;以及超過900個服務器版本&#xff0c;還有250…

讀書筆記(06) - 語法基礎 - JavaScript高級程序設計

寫在開頭 本篇是小紅書筆記的第六篇&#xff0c;也許你會奇怪第六篇筆記才寫語法基礎&#xff0c;筆者是不是穿越了。 答案當然是沒有&#xff0c;筆者在此分享自己的閱讀心得&#xff0c;不少人翻書都是從頭開始&#xff0c;結果永遠就只在前幾章。對此&#xff0c;筆者換了隨…

最近做了一個安裝包的安裝流程圖

最近到做安裝包的詳細設計。下圖是安裝包的流程圖&#xff0c;如果有什么意見和建議&#xff0c;希望大家給我留言&#xff0c;大家以前討論 轉載于:https://www.cnblogs.com/zengshengping815/archive/2009/04/22/1441319.html

如何使用Nikto漏洞掃描工具檢測網站安全

轉載鏈接&#xff1a;http://www.linuxidc.com/Linux/2011-02/32000.htm 【51CTO.com 獨家特稿】隨著信息技術的發展&#xff0c;網絡應用越來越廣泛&#xff0c;很多企業單位都依靠網站來運營&#xff0c;正因為業務的不斷提升和應用&#xff0c;致使網站的安全性顯得越來越重…

什么是區塊鏈預言機(BlockChain Oracle)

預言機 Oracle 是區塊鏈中非常重要的一個功能&#xff0c;但我發現很少有人討論&#xff0c;也可能很多人對此并不了解。而網上關于預言機的文章很少&#xff0c;很多也沒有講明白&#xff0c;甚至有些還是錯誤的。所以我整理了一篇詳細的文章&#xff0c;分享給大家&#xff0…

idea tomcat啟動成功但是訪問方面都是404_IDEA相關配置【集成Tomcatamp;項目部署】...

“知其然知其所以然”始終是Brick我學習新興技術的出發點&#xff0c;那么咱們來聊聊以下幾個問題問題1&#xff1a;在編寫完web項目之后&#xff0c;我們怎么才能運行項目呢&#xff1f;--需要部署項目到Tomcat上。問題2&#xff1a;部署項目到Tomcat服務器有多少種方式&#…

程序員素質面試題

技術題做完后&#xff0c;先檢查技術是否合格&#xff0c;技術合格的并非就一定是合適人選&#xff0c;還要做素質面試。 如下是小y出的面試題&#xff1a; &#xff08;上進心&#xff09;1.你的職業規劃是怎樣的&#xff0c;未來兩年想朝哪個方向發展&#xff1f; &#xff0…

用U盤或移動硬盤安裝Windows7 (超簡單制作Win7安裝U盤方法)

轉載鏈接&#xff1a;http://www.iplaysoft.com/win7-usb-dvd-download-tool.html 最近很多人想要安裝 Windows7 &#xff0c;下載回去后的ISO鏡像文件很多人都是使用 Nero 或 IMGBurn 等工具刻錄成光盤來安裝的。但實際上&#xff0c;不需刻盤安裝Win7的方法還是有不少的。…

安裝pywin32時:ImportError: DLL load failed: %1 不是有效的 Win32 應用程序和 DLL load failed...

問題一&#xff1a;ImportError: DLL load failed: %1 不是有效的 Win32 應用程序 import pywinapi報錯:ImportError: DLL load failed: %1 不是有效的 Win32 應用程序 原因&#xff1a;與python版本不對應 pypi官網上下載whl文件,我的python 版本為27 下載第一個后安裝 下載文…

pointcut注解_Spring AOP使用指南,詳細了解AOP相關注解

Spring AOP 指導教程什么是Spring AOP spring aop可以在spring構建的系統中使用面向切面編程。當然Spring Boot也是基于Spring構建的。使用AOP可以實現諸如事務&#xff0c;日志以及安全校驗等通過切面統一完成的任務。他可以通過簡單的注解方式實現在方法執行前后來執行你自己…

C# 實現FTP上傳與下載

向FTP服務器下載文件的簡單實例 Codestring filePath "d:\\"; string fileName "lhking.txt"; //文件下載之后要保存的路徑和文件名 FtpWebRequest reqFTP; try { FileStream outputStream …

Linux源碼安裝mysql 5.6.12(cmake編譯)

轉載鏈接&#xff1a;http://www.2cto.com/database/201307/229260.html Linux源碼安裝mysql 5.6.12&#xff08;cmake編譯&#xff09;1.安裝make編譯器(默認系統自帶)下載地址&#xff1a;http://www.gnu.org/software/make/[c-sharp] tar zxvf make-3.82.tar.gz cd make-3.…

云棲專輯 | 阿里開發者們的第6個感悟:享受折磨

2015年12月20日&#xff0c;云棲社區上線。2018年12月20日&#xff0c;云棲社區3歲。阿里巴巴常說“晴天修屋頂”。在我們看來&#xff0c;寒冬中&#xff0c;最值得投資的是學習&#xff0c;是增厚的知識儲備。所以社區特別制作了這個專輯——分享給開發者們20個彌足珍貴的成長…

python刪除數據庫的數據完整代碼_利用python操作小程序云數據庫實現簡單的增刪改查...

不止python&#xff0c;你可以利用任何語言那實現通過http請求來操作你自己的小程序云數據庫了背景也是在最近吧&#xff0c;小程序更新了云開發 HTTP API 文檔&#xff0c;提供了小程序外訪問云開發資源的能力&#xff0c;使用 HTTP API 開發者可在已有服務器上訪問云資源&…

AI技術在智能海報設計中的應用

背景 在視覺設計領域中&#xff0c;設計師們往往會因為一些簡單需求付出相當多的時間&#xff0c;比如修改文案內容&#xff0c;設計簡單的海報版式&#xff0c;針對不同機型、展位的多尺寸拓展等。這些工作需要耗費大量的時間、人力成本&#xff08;5~6張/人日&#xff09;&am…

javaScript如何監聽瀏覽器關閉事件

轉載鏈接&#xff1a;http://www.cnblogs.com/Tim_Liu/archive/2010/11/09/1872596.html 最近寫東西的時候發現需要對瀏覽器的關閉進行監聽,當用戶關閉的時候需要調用session.invalid();清空session信息,但是仔細一查手冊發現無論是body還是window都沒有onclose事件,之后onload…

C++樹的實現

C樹的實現 STL里面沒有提供容器樹的模板實現&#xff0c;自已寫一個&#xff1a;Tree.h //tree.h 頭文件 #include <list> #include <algorithm> using namespace std; struct TreeNode; //定義一個結構體原型 classTree; //定義一個類原型 classIterator; //定義一…

加密文件忘記密碼怎么解密_MyBatis 配置文件 用戶密碼加密存儲

properties配置文件一般是使用properties保存配置文件內容,然后在mybatis配置文件中進行讀取在resource文件下新建db.properties文件內容如下# 數據庫配置文件 driver com.mysql.cj.jdbc.Driver url jdbc:mysql:// /mybatis username password 然后,接著把文件放入源碼包…

PHP,如何防止同一用戶同一時間多次登錄

轉載鏈接&#xff1a;http://blog.sina.com.cn/s/blog_4832ea590101djnp.html PHP&#xff0c;如何防止同一用戶同一時間多次登錄&#xff1f; 創建表 username password sessionId 張三 123456 ksw9dkw9ksl92w3 備注&#xff1a;用戶…

科技前沿智能創新 2019北京智能家居 全屋智能博覽會

2019北京智能家居大型展覽會 2019北京全屋智能家居博覽會報道布展&#xff1a;2019年6月26日-27日 展會開幕&#xff1a;2019年6月28日上午9&#xff1a;00時展會交易&#xff1a;2019年6月28日-30日 展會撤展&#xff1a;2019年6月30日下午14&#xff1a;00時 展覽會在北京市政…