1. 程式人生 > >《零基礎入門學習Python》(20)--函式:內嵌函式和閉包

《零基礎入門學習Python》(20)--函式:內嵌函式和閉包

前言

之前我們講了函式的一些相關知識,瞭解了什麼是全域性變數什麼是區域性變數,接下來我們看看怎麼將區域性變數變為全域性變數。還要將將內嵌函式的相關概念

知識點

  • global關鍵字 
    使用global關鍵字,可以修改全域性變數:
>>> count = 5
>>> def Myfun():
        count = 10
        print(10)

>>> Myfun()
10
>>> print(count)
5
--------------------------------
>>> def Myfun():
        global count
        count = 10
        print(10)


>>> Myfun()
10
>>> print(count)
10
>>> 
--------------------- 
  • 內部函式 
    函式內部新建立另一個函式
>>> def fun1():
        print('fun1()正在被呼叫...')
        def fun2():
            print('fun2()正在被呼叫...')
        fun2()


>>> fun1()
fun1()正在被呼叫...
fun2()正在被呼叫...
  • 閉包(Closure) 
  • 如果在一個內部函式裡,對外部作用域(但不是在全域性作用域的)變數進行引用,那麼內部函式就會認為是閉包
>>> def FunX(x):
	def FunY(y):
		return x*y
	return FunY

>>> i =FunX(8)
>>> type(i)
<class 'function'>
>>> i(5)
40
>>> FunX(8)()#錯誤舉例
Traceback (most recent call last):
  File "<pyshell#17>", line 1, in <module>
    FunX(8)()
TypeError: FunY() missing 1 required positional argument: 'y'
>>> FunX(8)(5)
40
>>> FunY(5)
Traceback (most recent call last):
  File "<pyshell#19>", line 1, in <module>
    FunY(5)
NameError: name 'FunY' is not defined
>>> 
  • nonlocal關鍵字 
    用於宣告區域性變數
>>> def Fun1():
        x = 5
        def Fun2():
            x *= x
            return x
        return Fun2()

>>> Fun1()
Traceback (most recent call last):
  File "<pyshell#51>", line 1, in <module>
    Fun1()
  File "<pyshell#50>", line 6, in Fun1
    return Fun2()
  File "<pyshell#50>", line 4, in Fun2
    x *= x
UnboundLocalError: local variable 'x' referenced before assignment

原因:其存放在棧空間,如果修改,則會在區域性函式作用域中遮蔽外部變數,就會出現引用了沒有定義的變數值的錯誤。

解決辦法:在python3之前沒有直接的解決辦法,只能間接通過的容器來解決,因為容器型別不存放在棧裡邊,所以變數不會被遮蔽。

第一種解決方法:(因為佇列沒有存放在棧中)

>>> def Fun1():
        x = [5]
        def Fun2():
            x[0] *= x[0]
            return x[0]
        return Fun2()

>>> Fun1()
25

第二種解決方法:python3之後可以使用nonlocal關鍵字來解決了,在使用函式外部變數的時候在使用前先用關鍵字nonlocal宣告一下:

>>> def Fun1():
        x = 5
        def Fun2():
            nonlocal x
            x *= x
            return x
        return Fun2()

>>> Fun1()
25

課後作業

測試題

  • 如果希望在函式中修改全域性變數的值,應該使用什麼關鍵字?
global 關鍵字

例如:
>>> count = 5
>>> def MyFun():
                global count
                count = 10
                print(count)

>>> MyFun()
10
>>> count
10
  • 在巢狀的函式中,如果希望在內部函式修改外部函式的變數,應該使用什麼關鍵字?
#nolocal關鍵字

#例如:
>>> def Fun1():
                x = 5
                def Fun2():
                        nonlocal x
                        x *= x
                        return x
                return Fun2()

>>> Fun1()
25
  • Python的函式可以巢狀,但要注意訪問的作用域問題,請問以下程式碼存在什麼問題呢?
def outside():
    print('I am outside!')
    def inside():
        print('I am inside!')

inside()

使用巢狀函式要注意一點就是作用域問題,inside()函式是內嵌在outside()函式中的,所以除了outside()可以呼叫,在外邊或者別的函式體裡都無法對其進行呼叫的。

正確的呼叫應該是(注意空格的位置):

def outside():
    print('I am outside!')
    def inside():
        print('I am inside!')

    inside()
outside()
  • 請問為什麼程式碼A沒有報錯,但程式碼B卻報錯了?應該如何修改?
程式碼A:
>>> def outside():
        var = 5
        def inside():
            var = 3
            print(var)
        inside()

>>> outside()
3

程式碼B
>>> def outside():
    var = 5
    def inside():
        print(var)
        var = 3
    inside()

>>> outside()
Traceback (most recent call last):
  File "<pyshell#81>", line 1, in <module>
    outside()
  File "<pyshell#80>", line 6, in outside
    inside()
  File "<pyshell#80>", line 4, in inside
    print(var)
UnboundLocalError: local variable 'var' referenced before assignment

報錯原因分析:
說的是變數var沒有被定義就拿來使用,肯定錯啦!

這裡outside()函式裡有一個var變數,但要注意的是,內嵌函式inside()也有一個同名的變數,Python為了保護變數的作用域,故將outside()的var變數遮蔽起來,因此此時是無法訪問到外層的var變數的。

應該修改為:
>>> def outside():
        var = 5
        def inside():
            nonlocal var
            print(var)
            var = 3
        inside()

>>> outside()
5
  • 請問如何訪問funIn()呢?
>>> def funOut():
        def funIn():
            print('賓果!你成功訪問到我啦!')
        return funIn()

-------------直接呼叫----------------
>>> funOut()
賓果!你成功訪問到我啦!


>>> def funOut():
        def funIn():
            print('賓果!你成功訪問到我啦!')
        return funIn

>>> funOut
<function funOut at 0x000000A7EC476F28>
>>> funOut()
<function funOut.<locals>.funIn at 0x000000A7EC476E18>

>>> funOut()()
賓果!你成功訪問到我啦!
  • 以下是“閉包”的一個例子,請你目測下回列印什麼內容?
>>> def funX():
        x = 5
        def funY():
            nonlocal x
            x += 1
            return x
        return funY

>>> funX()()
6
>>> funX()()
6
>>> funX()()
6


>>> a = funX()
>>> print(a())
6
>>> print(a())
7
>>> print(a())
8

#有些魚油可能會比較疑惑,這怎麼跟全域性變數一樣了?區域性變數x不是應該在每次呼叫的時候都重新初始化了嗎?

#其實大家仔細看就明白了,當a = funX() 時,只要a變數沒有被重新賦值,funX()就沒有被釋放,也就是說區域性變數x就沒有被重新初始化。

所以當全域性變數不適用時,可考慮用閉包更穩定和安全,你還可以參考 

遊戲中的角色移動閉包在實際開發中的作用

動動手

請用已學過的知識編寫程式,統計下邊這個長字串各個字元出現的次數,並找到小甲魚送給大家的一句話。

string1 ='''%%[email protected]_$^__#)^)&!_+]!*@&^}@[@%]()%+$&[([email protected]%+%$*^@$^!+]!&_#)_*}{}}!}_]$[%}@[{[email protected]#_^{*
@##&{#&{&)*%(]{{([*}@[@&]+!!*{)!}{%+{))])[!^})+)$]#{*+^((@^@}$[**$&^{[email protected]#$%)[email protected](&
+^!{%_$&@^!}$_${)$_#)!({@!)(^}!*^&!$%_&&}&_#&@{)]{+)%*{&*%*&@%$+]!*__(#!*){%&@++
!_)^$&&%#+)}[email protected]!)&^}**#!_$([$!$}#*^}$+&#[{*{}{((#$]{[$[$$()_#}[email protected]}^@_&%^*!){*^^_$^
]@}#%[%!^[^_})[email protected]&}{@*!(@$%$^)}[_!}(*}#}#___}!](@_{{(*#%!%%+*)^+#%}$+_]#}%!**#!^_
省略大部分。
'''

list1 = []
for each in string1:
    if each not in list1:
        if each == '\\n':
            print('\\n',string1.count(each))
        else:
            print(each,string1.count(each))
        list1.append(each)

執行結果:

================= RESTART: C:\Users\ThinkPad\Desktop\test.py =================
% 26
$ 30
@ 28
_ 30
^ 27
# 24
) 26
& 25
! 33
+ 19
] 14
* 28
} 30
[ 15
( 18
{ 27

 6
省 1
略 1
大 1
部 1
分 1
。 1
  • 請用已學過的知識編寫程式,找出小甲魚藏在下邊這個長字串中的密碼,密碼的埋藏點符合以下規律:
1)每位密碼為單個小寫字母 
2)每位密碼的左右兩邊有且均只有三個大寫字母
str1 = '''ACFlCTLIQlAIVMTqHFkswqbDDHtpgcWaXSSglUYKE
lqNsYCyaQXBzrFUbkAUAWAKrDgDtAlGMBqWQhpEwquZqWZJpslUfMllCwWptqINjrOBTLuPzwvXNbLCx
oFRritKRpJgBOaGPZdkUzvYnvYmAlEsVmKRXqyQUOdCBqLYyboOYeAQNLnkuiDXCiNiksSSRpDMVQQgs
TmYThnppfKSmkpjjceGLaMOvYgsvNkGENKgGtUSzVPlLMeephDKrWGNpAxBqRiCnQIuKwDZurIRsznUp
xhstMWpHdZzqeEnttlAHiWbhbIJpwKBAGsFWthBiwBDKTFzIUamELZJFLbmqOmwBIYBJIofAUyxTLUEm
LcOXzjIHFcfUfEWccbWzhVuIZMdTVsOaNsLTpHjrvFaYTnJUrqaYnUmbobfOXXtkjKjFUEhVNlPWeaIY
uABNuEDKFWiUaqQiBHGsgEmDSKiJKLkkzFWlobXIyUlDzGcwDnEOwwWxgFpebsslmKItazIYctPROSJp
ImDHusQIkoFQSmuqwdcPNERvflfHtkGTrtbQXqZUsazoxmbVTPIuuxKvfALAaGnIuIZwczCcoIRMncBs
timFGHPJPaHMPTLjsBjIwbbzKyghaDTUStzJceaYAneywwpvdiUJifPHtXmAwZPChWsDmwonzeeQCEiB
xWsJLAtrdVEOBxEaYiSabHdUwlXlDOAKzZUwozJoBGvnFttDkXdYdjQSzzhTIPfYpWVFdiFIqSbyPZIi
VoXunBPbAJVMWluPcIfHmjPeHaTyClCvTOucEYEZXbVDiZMsfeuruDGMmQEsHutzvzVmWvCoPRguBiHh
taTeaguPmNuAxzYJLEcdoApfIFBaLUqettjTJNlHZYlJZRRoKXEvFnoUHdPjDuXuTAubGODkHAokpItw
SlEwhjrUSlfMawWlTMciWAzVcgPcqCHIaogokYAWGsvWZzBfJqzxIkCNvHDvBkOMCyeYXzVVuRJLQIOy
BMoVPgFLOagDxyPfWxTtZQNCLOrVVclPzMNYruNUyMOBKxBvinxuGMAAfndhPsROtkOJAAJQSxpmTzXm
CmEwZOhlItvETUneqvdKLghLyREjuJWRFjVVuNMiPuvvmRaEUmjCXDVuMRAvBuHUYGKPXthWISIbueRp
uvxpmqclmrXpAGFrxhJGxQwlrbkHEmcEUooCoPqGzbrCfIWmtUKmzzXvcqbhxKcAwXCNjbJDWDndKiLK
HwaFKyhXJQgHjIaTfIJrkhUpTHJZebRertDigQtDKxGerMRgHWFTrqqZlcBjAUfTZdFlZCAEZnhzgTIy
gJSsWJjFcCVoFonAfKPTOhTxjxTRtzSKLoIOScEwBCDvWFDVGpBOpijqdwvugoYsyuIOZJTcySDrzy
wBxediHOIYgasrUIDsNZcParqTGfTaBZHoSssXGtiCVvLReyoiitzMpsouqUeMHGWwDMgBaQTRkxPwNP
XsvyFVXfjgKuamMTsEsbeKDgAdVndyDleenPBcXWKGPcDsALDajkCEGufvbtyXUZnelqISbQnHphDoTH
RMIxMKclpWSvQHkzRhdAehBVaKYaXRPMpGaeRxvTRVFfewirvIDoGvYTAvKSoMFCLUNVFVKrYMeYtBrS
KgiBOjvliNOHLrmztypGhQjtpEQwzVfpVqsTUPvOCPzgqOuvLXJBQZHLmSwGTxEMgCAbogXombCiBDNX
BvGtXjrGWbWHtNCoRuqIZPhBQXZiNUhbmzOiyByAoMSBvusppiPVibIqmLXwXEVfcEAyNeUxaEZThULu
mkGmoLrpOEktwRluXvOmmfEWxZkxUNIqZKuzbaUmLKBYrXMmdOYLEzljzbSJnqRbSiAFyUNyyieKITkh
mvkKyosXKCaTsXQIKczJmxuqIEKeGGGwZyWTolQynlWngjDzFMlwhJFEmODeycbEfxgSRbIXySfwlhZZ
BUBhKyGBHRzWGRXAzarcmSDORvaOMOqYlcVIMwlHGtrLMhFWioqeKfvsJdTXmfQzavzSzCRrVzLFMaBT
DMOPFJcjzXcPvBkzacRmVKTQAvVobGRBypFHvoUdjvBhwWXVdDjvfJOocyIHbMqZGMaRaaFFnmtvTSkY
nIHbmPAtuEszMDFURBYxcOJXKMvJbfSbhiaacxhxiZBnoHTcFeqXQfjTqpcMKFpvvzkpSxlDxSlhikFZ
XSplcknpxiZfwUwGsrfpBUkevEiwndkKrVpWKufWpLTWXcyyXehOcDfnzgTAkhwOAcaiHqJWzsuAvMyD
pDJgeCdAJMwatRfcpKQGTkwxHracsYOlZeXoGthHIRfDBYzhuGEQRKFRnqSEbWDCJObWSAoSwFzVZEnI
rVBwXibUaTwnSTwRmIwkIgoGPRiOMLOTvnzEBBCfcugYZwGSsHRKCJoRsxxzRkKwnTRcRNfbMGssqmXV
IKYzyWHIsCjdzxiHEtvHaufVgcoqVkqIQertevTUTIVMYlNXCGEUzQowqsFpciURKoUwqCRogxeghOWs
cMnuAathgFvNIVqqXpmdJDJPhXQpZCyNbTYktMyTUtQEBeQBhEZzqHotmYREADhFodlcPmTMutBZyefW
sBmsnUbVnHUGAyaDirMoowBwXnzrmfHJgfpAquFoHTuvQvIJcjqiqVdntXbgwpVywbsKxqUMNxYVxBmQ
OAcxOAVPuJeOgABYEHhevhnUOgCUuTBAhJcUGsasbMInGCbHnHXWDdXijDRkUYFuOytTcMPtWklmTHTR
XFTfcFfSSqFUFbQVCKEjUOLveXtsHrIfkphXyDkRELnaTfuaZUClLqbdpWAREJHJpycYRDjElqlVeNya
kTCjDpvFrdnlXogrDZdQzAYaePDdfvHWdcaQGgrrHKBdMnMYbsikbkffVsITSUhEapmLGQYbHoiKGRcg
GPLeEvmCOAkGIuDBdnYPlzuUmLOfetGXpbTbPjjWCZiOJxlDazSbEPVpnNLDsLiwlgleiCdPezQwnNWT
ECLuRGpfJZlnZtcghLucmvlOZNwXaikbKGmoGZJIcsfNnmaHIcPXiEYDHjLKpVtNsqemAmaiTIzvLqlU
mlcvraikZozZwBoExUkELoiaAbTAkqDhrARHQyAvWvYUjthfWjZqbQNTnkgmySsORxGcxouYcyCSkjmC
fpTGOlFoXWLINurMZdQURRnZCiZqsEKeVVZdFMnaoUepdAdARtUuXTvkGzmpEVNZiYSWJAwkcSKgAWTD
mUNVxVebIiavuOAxWUBkuUkXCYtRoZhVNwCZGlaANNpBvXgSDeLURUdQnQteKAXbGlOLGYYYCzCGjzua
UmrdPYuRrUBvLFfwBGTiABTmpANdPCptqKwWXARMKrtmbggOBDgNkeHzNUCIXUIuOAavRbLTnzNNRgzL
boTJooLJIdVFbbjWNngnzPznJglCLEWqulqzSuAyvqYdivDqxEtYPKTwVheFmDidEOnLqjPHBcjoOVvt
MCDmQfwNxkOPuxiJqLQOPRAGJappmpikgmrvRAlKjFjTlaznQldBJmzSMDvCWghWOgfhfkHFZBNdbmMf
MsaQHrtJQvZuGFCrPVBNSNZBFZRdpmQNZYZXpkGjXRAXhELlxDfGhiXwgAUujQbqUCiKaRIYruNDRDlL
zInUkJBpySRZoqwQlqmoxADBjjtGjFPLTkcexYGwGYlANZQaXNgKkPXUUqlViVzxPxxtMQPqOxTcChCg
dvKNliVwzRfMmSsBFeuePnbmVqvyfdOXnZpUopEqfCMnnXpfZnNYwNKiZFPUWWmNCMibsyQEhiodVjTz
UxsicVsZNMXyvBLrdJxGGeCPEutNCzYBRamXwRlmVdqUTPnUoAWaVDshgTHZhvhVlLZsoqbyqOjJMPac
hHqiCKhgFkDUhUDSwsrEwaBrKhXINTjYmHvsTyFdRHliydbfQtRFZcsSTfcSfqyIgQuXLZnrdAwylBmW
BRbmVwdoNFcnoxMKHaYOhgihIsKitcrgEkfjIOKsDPOadFhMwVSKWeCfxxxfWjgNiGDaiYDtMhCgedOR
nTYoeVrpGsyDIsuKhffqaEqoqfWukaQlcUShYicuZAdoYVGvRchUgcmNwxQGogDvKhyAkIuqHCIXQfXp
CtkSSTXTugolUKfqSzugIOpyHhIlcTjDBTKPqcyaRhmgFdSBkYurnvnukNGVoxpZBFmwIEmehuaUcoeu
btkjJqKcAAqxgrKcoRGuqHVUHqKgEaqRCIXlaTqaUewJBEWnTnTJIDYdLeGUMDfndHPYTAGQbhxreADo
WZtdvbJVnNGRNvlAsqIPlpXSXEZGBdqVyNCCwylcXprVoGqnPXZioKnqbdrYlDhbsTVDJqRQKoPtQXzu
RnrGgCfYfeRRxiihjItxHurPwtYJoObDzlEABeIRxQocvWrJtyWchmZXJdYvTgicUircdiMKYAkNbdKu
gPpzXnTQIZxtIhvfBfjIHRaDXbYExxYBvrejpEaVHlinHlYRrhsbChnAwTKlQtHntqcqiXZwTUEdlsVy
WFdZNRfqzkhWzeKMGmkuKoSkuSZRkddsuBNFVMFLPeUkLwCCDKagNjMZwtHcVcEEKyjAYubHipuqNjaV
JukystpMZrhBgLqRVMpaIPsyAvYIsBDVqKNCMLqLwyhJhuWDdCPBgSzJTLkJvaGPirOFwfuMtkyXeKoZ
rGPRJqXyhdYNOXVSqGvbSPozAbjhpyfgGVuNUYaRQomzrTtzAMJnYnyvDnuBkbVvmYzhlhqmwgCZaGJG
GGRbaFdfnDlUfCfhpDWTkWfpUDuUksJvRFNxVYBKGoxBCdhmYZwyDPzWihcQXgByRbYxWZslVsbuTHTf
vaulICCTRkkiYuYoqFdzuxsqOBkzEJHbNXhSnHYxyeGoEklCeaUVEtjxmXyOEzcpsAhfKCTejxOxwGYh
eLtoPpPINviTCHUsgzSkycIxtvekMaoZkBIyLboyvMxxaqfviBxkSALNjiNYqGTypcZDvHonaVBZCSLp
SjRTsJmDuPwKnYwCdTprFvbXnrhARNToXpryIfEoIwSWIdfSKeOHDYwgyUvwXXpKUKQEiyZxCsTkAjME
hdxShAAUYJTkprXuFITxxJuKMiphRAyAeUFZgknMMLvUaSjiMlGmLARvTMpllxEQyfvEqkcONHVFcaTW
tqcbVrgeTLTGuJsrjZdYrrjtoLKcEfjkIhjzXgEkYhZggujFJuQlVtSqvuejtxAEqjgXrYjmwLkSRmXp
pkTfONxRyAxRYqJccLxuhabwMTWfwLTlzuVGJtVJOXxwKjFIZENpGHwRvTRitDBQBesRYATKhmWmmmbP
EXOzdBHNeghlqpjJFmzXyADNHQNEThWDyMsGsTmyFnywIPvDSIcxHbKQHgmJEcfsPzYvSYIbQjnTAgzF
UfZAbwfgCMRxtmZQQyayJFFhCSVeeUcQzSLWqhENNUpyLZaJsQsFQsPyFIjGtcmoJaFQGKTFtKUBdBBo
xECKHgYSMcBWnzRvPyihfjwyjhTTavfYqOrbrgZDSrwVYFjNsdxLJIigfMgythUoUIVSydOnfhAaesXZ
kfyDztQiBCMHjfEGLFllxfejLJjanZVRENsXhIxSWDgbvHHOAFtHzqdfquGbdQvOFlhDiWpxwEolxbep
fVfpKYGMNIQuOlmtTkNRDFTVMtVkEXYUDZKfEihbxXsSLGDcKSHSMXZxAturZVEQgismVAgMVVatqjBM
rXeHaGdccPJMlqhVAePDyEoIRTLCwJpkNTuOjEKEvXaAGhWmhWPHCBMVPkcPklbGIvzMzOFplRUsvZbE
vScmmoKktOUVOeKBcqVvoSsplqqssDvLiPqucbrxoNkodsbrZnvoDfyNGyUAURseEuJPUWsEiVCNcUNd
sxzoRVpEFuFloqWLumNVJITKXnWnOlGpCaQgTLJYizixXoxAHHbodRtPHBbnSzZRZOmlWKOQqvHWAhDh
cYBGRQsFwyesMILhiwjnvjeMIZnHYHYNrmOahjrVPuRgsxdfgUbKCZAVfcOizDeQLKiFQmQQUlDHnCQe
lMnlLSrtXhmGDqISCgElUrZXbXjGGkdWadBbxzVojGQwyhAbWMhSKFFwoIqJfIDdZjUdfCYFkpDdIuWe
aFIUFhnlsREthBRoaquSzBVVOPABfuAYZpoalZwNfZMPOptcoQYVUdRYlXuYChPAdRJgFgwPyTszSXIe
qHRtMxyNlPGoBfpjxHnNvwIADmJmquLgMQGtpJAyvflZjFwAgIymerCTnVkjvqPKFVRscOqAhqvCqCjw
BBojzXKIdphOVTFKhBpnIWYRfuqvQZgVMaqNBkYKzqGaEnBFKZukSLdPbXNmcZtMeykLwlLbZqaHayOb
IWZvbxEXXnaozCHeyiYMnWqIAwJxhMIPDsgySMKhdBYmdrGdbJOfJralshwvhWlmatTsylewdimJEzph
tuTzSGOkGDPPvltRVJPdHRPBTAsKWncfjjuHdlEVOeZIvVnUFHmyGTFDlMGVyAIdzLocbTXIHYTopIok
UHFAVjEXPlsMoKTriyGnfeTlVzvGhVZzUAWWPdZNdIxKioQylFMJZmSToyRGsDJKJXQxPkINvmoHCVUc
RIjImkWWxTnDLQiXdmHqQrWBuvguUUubGByTRnJfkNWxsSupcfIVgboDWzqYHEfAnIKCfdYUOslfXPax
YnaJfNLqJgcxRjBmRpOYgNpZOpzMOCVIRiiXdIqqFxPJhQqJadKiCesOsZoWGWbbQSVRZUlbNZdzeUTE
nhdMSCKCPbpWZguZHGkLiWCisjqnaLbJpbRFAHPjGbHOXKZQXoQQZohmVqjTcdWNhXEjPlLKnjpwbMPQ
ybzDvGgkybXtbDmjQuyOrMrcYGRGGfuuPXzieaetSBidnSRPsLaXKGcxDkXmHbqMWZJXsQkwtojlxOeU
KSIFdVvNEnOUmIZDdlnwtJcPBlcpRWNTazpzgItwJotSLWZruzrMlSGASMWDwOqTpeYYHaTHCCurPdwB
AWzUtwblZXNrBYdjUoDacvmRVURqOzUPlnFISsZMFPtthnDHSsFgkYfsMtXFuNPhLTleWVrmelyFaemo
bVIhEAxNwOUDQCOCDIBHsQlFxCbHErKiBsvQNjuIGnIzZiwoVTdUZnucSaKdHrxJeGQfTawFJefGJFFa
GHzELfnGBmkZyorbbDDwhvEVeIYIGLPMEuZduqFjbeWbVfzVIRZNXwPLgcYUsevuhEQXfYcJshYnJaWz
iqvlswEBRKNYEJidlzdWnQJpBtyjHYVpkQGzdYkeREqjhmmnUIbGZVnwwaMKqgXfURSICNxdteUSGhGZ
UEEFhWRoTKGRwFmPpZPOsalsrNOlkTdXqGKoWlWkqJvYYrtLiTfhdItMbbhdumSYgCcQVUARnYFWkCsC
jElZxrQHIlbTHFLOnrutlvyxzaSIdkJgeyMUnUmtXfnaIedbAInAuQssOQqBTLbvFRiqKqUSdUEmcRmN
LvAxlgliymfbjTwDSqNTLcAEIerzpUShNKkuehciEAYeGJOFFcOvurJFUyfZhQqzfaneiBcrPhaphSCB
StQiJvtoPhHcLUbriDUIfifVFnNtJfGlmcbQJSXsZfVjpbqnkMllUmHzLvEuSarSlNlNHsWvYlfhjMEA
epYTjoRGZeAAtURFeDfDxTYmOmONuQQBdcdncFGjhHmKlwqmUWoXuIXIxaaXnNThgPGtIlynrUIPLQTG
xXhattDrfBGbZRveKbgjzxJLdYREQlMeLtcIEUoyJocdAfUbymxuFLVjGkOQniiPParqoyQYfDYAQTkM
WLicLxpEFkBbwlKrTyYilKTtYkpVGxtOjYmcBDOrwFhFiGutmpTyTarUbVUeSevBTdaPDpjRkaEmLJMg
WsMhSGfIcBChcqrRKgKpjvGnFipjswgjetRtniMagakbCXAjpzWTtMlgZGCJwGyglpcLebrKWhgwJfWV
qGifWNEpCtjuejHoyVCdIxzMYGnfoslgTNAJdtVBWDVoGLzHSAVBTnhNIvAOExQNiJOIPPiHkdaRbfaP
ixDDoCDOOeAqvQJFxLWDICfGmufyxmaMshbvcrtjqqVtffZTnbtCOQfzRMGwOQEKaAmSWjnYdNgvdkmd
dQmaKZSdqKNrnvJlcyVMKuNWmuoOeyKecgjXbmSqnpjwJEaDYoehEklEgJyiksGxdEKgfYRXQecRZgfe
qKWGc'''


countA = 0  # 統計前邊的大寫字母
countB = 0  # 統計小寫字母
countC = 0  # 統計後邊的大寫字母
length = len(str1)

for i in range(length):
    if str1[i] == '\n':
        continue

    """
    |如果str1[i]是大寫字母:
    |-- 如果已經出現小寫字母:
    |-- -- 統計後邊的大寫字母
    |-- 如果未出現小寫字母:
    |-- -- 清空後邊大寫字母的統計
    |-- -- 統計前邊的大寫字母
    """
    if str1[i].isupper():
        if countB:
            countC += 1
        else:
            countC = 0
            countA += 1

    """
    |如果str1[i]是小寫字母:
    |-- 如果小寫字母前邊不是三個大寫字母(不符合條件):
    |-- -- 清空所有記錄,重新統計
    |-- 如果小寫字母前邊是三個大寫字母(符合條件):
    |-- -- 如果已經存在小寫字母:
    |-- -- -- 清空所有記錄,重新統計(出現兩個小寫字母)
    |-- -- 如果該小寫字母是唯一的:
    |-- -- -- countB記錄出現小寫字母,準備開始統計countC
    """
    if str1[i].islower():
        if countA != 3:
            countA = 0
            countB = 0
            countC = 0
        else: 
            if countB:
                countA = 0
                countB = 0
                countC = 0
            else:
                countB = 1
                countC = 0
                target = i

    """
    |如果前邊和後邊都是三個大寫字母:
    |-- 如果後邊第四個字母也是大寫字母(不符合條件):
    |-- -- 清空記錄B和C,重新統計
    |-- 如果後邊僅有三個大寫字母(符合所有條件):
    |-- -- 列印結果,並清空所有記錄,進入下一輪統計
    """
    if countA == 3 and countC == 3:
        if i+1 != length and str1[i+1].isupper():
            countB = 0
            countC = 0
        else:
            print(str1[target], end='')
            countA = 3
            countB = 0
            countC = 0


執行結果:
================= RESTART: C:\Users\ThinkPad\Desktop\test.py =================
ilovefishc