面向對象之繼承與派生

一 初識繼承

什么是繼承

繼承是一種創建新類的方式,新建的類可以繼承一個或多個父類(python支持多繼承),父類又可稱為基類或超類,新建的類稱為派生類或子類。

子類會“”遺傳”父類的屬性,從而解決代碼重用問題(比如練習7中Garen與Riven類有很多冗余的代碼)

python中類的繼承分為:單繼承和多繼承

復制代碼
class ParentClass1: #定義父類passclass ParentClass2: #定義父類passclass SubClass1(ParentClass1): #單繼承,基類是ParentClass1,派生類是SubClasspassclass SubClass2(ParentClass1,ParentClass2): #python支持多繼承,用逗號分隔開多個繼承的類pass
復制代碼

查看繼承

>>> SubClass1.__bases__ #__base__只查看從左到右繼承的第一個子類,__bases__則是查看所有繼承的父類
(<class '__main__.ParentClass1'>,)
>>> SubClass2.__bases__
(<class '__main__.ParentClass1'>, <class '__main__.ParentClass2'>)

經典類與新式類

1.只有在python2中才分新式類和經典類,python3中統一都是新式類
2.在python2中,沒有顯式的繼承object類的類,以及該類的子類,都是經典類
3.在python2中,顯式地聲明繼承object的類,以及該類的子類,都是新式類
3.在python3中,無論是否繼承object,都默認繼承object,即python3中所有類均為新式類
#關于新式類與經典類的區別,我們稍后討論

提示:如果沒有指定基類,python的類會默認繼承object類,object是所有python類的基類,它提供了一些常見方法(如__str__)的實現。

>>> ParentClass1.__bases__
(<class 'object'>,)
>>> ParentClass2.__bases__
(<class 'object'>,)

二 繼承與抽象(先抽象再繼承)

繼承描述的是子類與父類之間的關系,是一種什么是什么的關系。要找出這種關系,必須先抽象再繼承

抽象即抽取類似或者說比較像的部分。

抽象分成兩個層次:?

1.將奧巴馬和梅西這倆對象比較像的部分抽取成類;?

2.將人,豬,狗這三個類比較像的部分抽取成父類。

抽象最主要的作用是劃分類別(可以隔離關注點,降低復雜度)

?

繼承:是基于抽象的結果,通過編程語言去實現它,肯定是先經歷抽象這個過程,才能通過繼承的方式去表達出抽象的結構。

抽象只是分析和設計的過程中,一個動作或者說一種技巧,通過抽象可以得到類

?

三 繼承與重用性

==========================第一部分
例如貓可以:喵喵叫、吃、喝、拉、撒狗可以:汪汪叫、吃、喝、拉、撒如果我們要分別為貓和狗創建一個類,那么就需要為 貓 和 狗 實現他們所有的功能,偽代碼如下:#貓和狗有大量相同的內容
class 貓:def 喵喵叫(self):print '喵喵叫'def 吃(self):# do somethingdef 喝(self):# do somethingdef 拉(self):# do somethingdef 撒(self):# do somethingclass 狗:def 汪汪叫(self):print '喵喵叫'def 吃(self):# do somethingdef 喝(self):# do somethingdef 拉(self):# do somethingdef 撒(self):# do something==========================第二部分
上述代碼不難看出,吃、喝、拉、撒是貓和狗都具有的功能,而我們卻分別的貓和狗的類中編寫了兩次。如果使用 繼承 的思想,如下實現:動物:吃、喝、拉、撒貓:喵喵叫(貓繼承動物的功能)狗:汪汪叫(狗繼承動物的功能)偽代碼如下:
class 動物:def 吃(self):# do somethingdef 喝(self):# do somethingdef 拉(self):# do somethingdef 撒(self):# do something# 在類后面括號中寫入另外一個類名,表示當前類繼承另外一個類
class 貓(動物):def 喵喵叫(self):print '喵喵叫'# 在類后面括號中寫入另外一個類名,表示當前類繼承另外一個類
class 狗(動物):def 汪汪叫(self):print '喵喵叫'==========================第三部分
#繼承的代碼實現
class Animal:def eat(self):print("%s 吃 " %self.name)def drink(self):print ("%s 喝 " %self.name)def shit(self):print ("%s 拉 " %self.name)def pee(self):print ("%s 撒 " %self.name)class Cat(Animal):def __init__(self, name):self.name = nameself.breed = ''def cry(self):print('喵喵叫')class Dog(Animal):def __init__(self, name):self.name = nameself.breed=''def cry(self):print('汪汪叫')# ######### 執行 #########

c1 = Cat('小白家的小黑貓')
c1.eat()c2 = Cat('小黑的小白貓')
c2.drink()d1 = Dog('胖子家的小瘦狗')
d1.eat()
使用繼承來重用代碼比較好的例子

?在開發程序的過程中,如果我們定義了一個類A,然后又想新建立另外一個類B,但是類B的大部分內容與類A的相同時

我們不可能從頭開始寫一個類B,這就用到了類的繼承的概念。

通過繼承的方式新建類B,讓B繼承A,B會‘遺傳’A的所有屬性(數據屬性和函數屬性),實現代碼重用

class Hero:def __init__(self,nickname,aggressivity,life_value):self.nickname=nicknameself.aggressivity=aggressivityself.life_value=life_valuedef move_forward(self):print('%s move forward' %self.nickname)def move_backward(self):print('%s move backward' %self.nickname)def move_left(self):print('%s move forward' %self.nickname)def move_right(self):print('%s move forward' %self.nickname)def attack(self,enemy):enemy.life_value-=self.aggressivity
class Garen(Hero):passclass Riven(Hero):passg1=Garen('草叢倫',100,300)
r1=Riven('銳雯雯',57,200)print(g1.life_value)
r1.attack(g1)
print(g1.life_value)'''
運行結果
243
'''
View Code

提示:用已經有的類建立一個新的類,這樣就重用了已經有的軟件中的一部分設置大部分,大大生了編程工作量,這就是常說的軟件重用,不僅可以重用自己的類,也可以繼承別人的,比如標準庫,來定制新的數據類型,這樣就是大大縮短了軟件開發周期,對大型軟件開發來說,意義重大.

注意:像g1.life_value之類的屬性引用,會先從實例中找life_value然后去類中找,然后再去父類中找...直到最頂級的父類。

重點!!!:再看屬性查找

class Foo:def f1(self):print('Foo.f1')def f2(self):print('Foo.f2')self.f1()class Bar(Foo):def f1(self):print('Foo.f1')b=Bar()
b.f2()
View Code

四 派生

當然子類也可以添加自己新的屬性或者在自己這里重新定義這些屬性(不會影響到父類),需要注意的是,一旦重新定義了自己的屬性且與父類重名,那么調用新增的屬性時,就以自己為準了。

class Riven(Hero):camp='Noxus'def attack(self,enemy): #在自己這里定義新的attack,不再使用父類的attack,且不會影響父類print('from riven')def fly(self): #在自己這里定義新的print('%s is flying' %self.nickname)

在子類中,新建的重名的函數屬性,在編輯函數內功能的時候,有可能需要重用父類中重名的那個函數功能,應該是用調用普通函數的方式,即:類名.func(),此時就與調用普通函數無異了,因此即便是self參數也要為其傳值

復制代碼
class Riven(Hero):camp='Noxus'def __init__(self,nickname,aggressivity,life_value,skin):Hero.__init__(self,nickname,aggressivity,life_value) #調用父類功能self.skin=skin #新屬性def attack(self,enemy): #在自己這里定義新的attack,不再使用父類的attack,且不會影響父類Hero.attack(self,enemy) #調用功能print('from riven')def fly(self): #在自己這里定義新的print('%s is flying' %self.nickname)r1=Riven('銳雯雯',57,200,'比基尼')
r1.fly()
print(r1.skin)'''
運行結果
銳雯雯 is flying
比基尼'''
復制代碼

五 組合與重用性

軟件重用的重要方式除了繼承之外還有另外一種方式,即:組合

組合指的是,在一個類中以另外一個類的對象作為數據屬性,稱為類的組合

復制代碼
>>> class Equip: #武器裝備類
...     def fire(self):
...         print('release Fire skill')
... 
>>> class Riven: #英雄Riven的類,一個英雄需要有裝備,因而需要組合Equip類
...     camp='Noxus'
...     def __init__(self,nickname):
...         self.nickname=nickname
...         self.equip=Equip() #用Equip類產生一個裝備,賦值給實例的equip屬性
... 
>>> r1=Riven('銳雯雯')
>>> r1.equip.fire() #可以使用組合的類產生的對象所持有的方法
release Fire skill
復制代碼

?

組合與繼承都是有效地利用已有類的資源的重要方式。但是二者的概念和使用場景皆不同,

1.繼承的方式

通過繼承建立了派生類與基類之間的關系,它是一種'是'的關系,比如白馬是馬,人是動物。

當類之間有很多相同的功能,提取這些共同的功能做成基類,用繼承比較好,比如老師是人,學生是人

2.組合的方式

用組合的方式建立了類與組合的類之間的關系,它是一種‘有’的關系,比如教授有生日,教授教python和linux課程,教授有學生s1、s2、s3...

class People:def __init__(self,name,age,sex):self.name=nameself.age=ageself.sex=sexclass Course:def __init__(self,name,period,price):self.name=nameself.period=periodself.price=pricedef tell_info(self):print('<%s %s %s>' %(self.name,self.period,self.price))class Teacher(People):def __init__(self,name,age,sex,job_title):People.__init__(self,name,age,sex)self.job_title=job_titleself.course=[]self.students=[]class Student(People):def __init__(self,name,age,sex):People.__init__(self,name,age,sex)self.course=[]egon=Teacher('egon',18,'male','沙河霸道金牌講師')
s1=Student('牛榴彈',18,'female')python=Course('python','3mons',3000.0)
linux=Course('python','3mons',3000.0)#為老師egon和學生s1添加課程
egon.course.append(python)
egon.course.append(linux)
s1.course.append(python)#為老師egon添加學生s1
egon.students.append(s1)#使用
for obj in egon.course:obj.tell_info()
例子:繼承與組合

當類之間有顯著不同,并且較小的類是較大的類所需要的組件時,用組合比較好

六 接口與歸一化設計

1.什么是接口

=================第一部分:Java 語言中的接口很好的展現了接口的含義: IAnimal.java
/*
* Java的Interface接口的特征:
* 1)是一組功能的集合,而不是一個功能
* 2)接口的功能用于交互,所有的功能都是public,即別的對象可操作
* 3)接口只定義函數,但不涉及函數實現
* 4)這些功能是相關的,都是動物相關的功能,但光合作用就不適宜放到IAnimal里面了 */package com.oo.demo;
public interface IAnimal {public void eat();public void run(); public void sleep(); public void speak();
}=================第二部分:Pig.java:豬”的類設計,實現了IAnnimal接口 
package com.oo.demo;
public class Pig implements IAnimal{ //如下每個函數都需要詳細實現public void eat(){System.out.println("Pig like to eat grass");}public void run(){System.out.println("Pig run: front legs, back legs");}public void sleep(){System.out.println("Pig sleep 16 hours every day");}public void speak(){System.out.println("Pig can not speak"); }
}=================第三部分:Person2.java
/*
*實現了IAnimal的“人”,有幾點說明一下: 
* 1)同樣都實現了IAnimal的接口,但“人”和“豬”的實現不一樣,為了避免太多代碼導致影響閱讀,這里的代碼簡化成一行,但輸出的內容不一樣,實際項目中同一接口的同一功能點,不同的類實現完全不一樣
* 2)這里同樣是“人”這個類,但和前面介紹類時給的類“Person”完全不一樣,這是因為同樣的邏輯概念,在不同的應用場景下,具備的屬性和功能是完全不一樣的 */package com.oo.demo;
public class Person2 implements IAnimal { public void eat(){System.out.println("Person like to eat meat");}public void run(){System.out.println("Person run: left leg, right leg");}public void sleep(){System.out.println("Person sleep 8 hours every dat"); }public void speak(){System.out.println("Hellow world, I am a person");} 
}=================第四部分:Tester03.java
package com.oo.demo;public class Tester03 {public static void main(String[] args) {System.out.println("===This is a person==="); IAnimal person = new Person2();person.eat();person.run();person.sleep();person.speak();System.out.println("\n===This is a pig===");IAnimal pig = new Pig();pig.eat();pig.run();pig.sleep();pig.speak();} 
}
java中的interface

PS:hi boy,給我開個查詢接口。。。此時的接口指的是:自己提供給使用者來調用自己功能的方式\方法\入口

2. 為何要用接口

接口提取了一群類共同的函數,可以把接口當做一個函數的集合。

然后讓子類去實現接口中的函數。

這么做的意義在于歸一化,什么叫歸一化,就是只要是基于同一個接口實現的類,那么所有的這些類產生的對象在使用時,從用法上來說都一樣。

?

歸一化的好處在于:

1. 歸一化讓使用者無需關心對象的類是什么,只需要的知道這些對象都具備某些功能就可以了,這極大地降低了使用者的使用難度。

2. 歸一化使得高層的外部使用者可以不加區分的處理所有接口兼容的對象集合

2.1:就好象linux的泛文件概念一樣,所有東西都可以當文件處理,不必關心它是內存、磁盤、網絡還是屏幕(當然,對底層設計者,當然也可以區分出“字符設備”和“塊設備”,然后做出針對性的設計:細致到什么程度,視需求而定)。

2.2:再比如:我們有一個汽車接口,里面定義了汽車所有的功能,然后由本田汽車的類,奧迪汽車的類,大眾汽車的類,他們都實現了汽車接口,這樣就好辦了,大家只需要學會了怎么開汽車,那么無論是本田,還是奧迪,還是大眾我們都會開了,開的時候根本無需關心我開的是哪一類車,操作手法(函數調用)都一樣

3. 模仿interface

在python中根本就沒有一個叫做interface的關鍵字,如果非要去模仿接口的概念

可以借助第三方模塊:

http://pypi.python.org/pypi/zope.interface

twisted的twisted\internet\interface.py里使用zope.interface

文檔https://zopeinterface.readthedocs.io/en/latest/

設計模式:https://github.com/faif/python-patterns

?

也可以使用繼承:?

繼承的兩種用途

一:繼承基類的方法,并且做出自己的改變或者擴展(代碼重用):實踐中,繼承的這種用途意義并不很大,甚至常常是有害的。因為它使得子類與基類出現強耦合。

二:聲明某個子類兼容于某基類,定義一個接口類(模仿java的Interface),接口類中定義了一些接口名(就是函數名)且并未實現接口的功能,子類繼承接口類,并且實現接口中的功能

class Interface:#定義接口Interface類來模仿接口的概念,python中壓根就沒有interface關鍵字來定義一個接口。def read(self): #定接口函數readpassdef write(self): #定義接口函數writepassclass Txt(Interface): #文本,具體實現read和writedef read(self):print('文本數據的讀取方法')def write(self):print('文本數據的讀取方法')class Sata(Interface): #磁盤,具體實現read和writedef read(self):print('硬盤數據的讀取方法')def write(self):print('硬盤數據的讀取方法')class Process(Interface):def read(self):print('進程數據的讀取方法')def write(self):print('進程數據的讀取方法')
View Code

上面的代碼只是看起來像接口,其實并沒有起到接口的作用,子類完全可以不用去實現接口?,這就用到了抽象類

七 抽象類

1 什么是抽象類

? ? 與java一樣,python也有抽象類的概念但是同樣需要借助模塊實現,抽象類是一個特殊的類,它的特殊之處在于只能被繼承,不能被實例化

2 為什么要有抽象類

? ? 如果說類是從一堆對象中抽取相同的內容而來的,那么抽象類是從一堆中抽取相同的內容而來的,內容包括數據屬性和函數屬性。

  比如我們有香蕉的類,有蘋果的類,有桃子的類,從這些類抽取相同的內容就是水果這個抽象的類,你吃水果時,要么是吃一個具體的香蕉,要么是吃一個具體的桃子。。。。。。你永遠無法吃到一個叫做水果的東西。

? ? 從設計角度去看,如果類是從現實對象抽象而來的,那么抽象類就是基于類抽象而來的。

  從實現角度來看,抽象類與普通類的不同之處在于:抽象類中只能有抽象方法(沒有實現功能),該類不能被實例化,只能被繼承,且子類必須實現抽象方法。這一點與接口有點類似,但其實是不同的,即將揭曉答案

3. 在python中實現抽象類

#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'
#一切皆文件
import abc #利用abc模塊實現抽象類class All_file(metaclass=abc.ABCMeta):all_type='file'@abc.abstractmethod #定義抽象方法,無需實現功能def read(self):'子類必須定義讀功能'pass@abc.abstractmethod #定義抽象方法,無需實現功能def write(self):'子類必須定義寫功能'pass# class Txt(All_file):
#     pass
#
# t1=Txt() #報錯,子類沒有定義抽象方法class Txt(All_file): #子類繼承抽象類,但是必須定義read和write方法def read(self):print('文本數據的讀取方法')def write(self):print('文本數據的讀取方法')class Sata(All_file): #子類繼承抽象類,但是必須定義read和write方法def read(self):print('硬盤數據的讀取方法')def write(self):print('硬盤數據的讀取方法')class Process(All_file): #子類繼承抽象類,但是必須定義read和write方法def read(self):print('進程數據的讀取方法')def write(self):print('進程數據的讀取方法')wenbenwenjian=Txt()yingpanwenjian=Sata()jinchengwenjian=Process()#這樣大家都是被歸一化了,也就是一切皆文件的思想
wenbenwenjian.read()
yingpanwenjian.write()
jinchengwenjian.read()print(wenbenwenjian.all_type)
print(yingpanwenjian.all_type)
print(jinchengwenjian.all_type)
View Code

4. 抽象類與接口

抽象類的本質還是類,指的是一組類的相似性,包括數據屬性(如all_type)和函數屬性(如read、write),而接口只強調函數屬性的相似性。

抽象類是一個介于類和接口直接的一個概念,同時具備類和接口的部分特性,可以用來實現歸一化設計?

八?繼承實現的原理(可惡的菱形問題)

1 繼承順序

在Java和C#中子類只能繼承一個父類,而Python中子類可以同時繼承多個父類,如A(B,C,D)

如果繼承關系為非菱形結構,則會按照先找B這一條分支,然后再找C這一條分支,最后找D這一條分支的順序直到找到我們想要的屬性

如果繼承關系為菱形結構,那么屬性的查找方式有兩種,分別是:深度優先和廣度優先

class A(object):def test(self):print('from A')class B(A):def test(self):print('from B')class C(A):def test(self):print('from C')class D(B):def test(self):print('from D')class E(C):def test(self):print('from E')class F(D,E):# def test(self):#     print('from F')pass
f1=F()
f1.test()
print(F.__mro__) #只有新式才有這個屬性可以查看線性列表,經典類沒有這個屬性#新式類繼承順序:F->D->B->E->C->A
#經典類繼承順序:F->D->B->A->E->C
#python3中統一都是新式類
#pyhon2中才分新式類與經典類

繼承順序
View Code

2 繼承原理(python如何實現的繼承)

python到底是如何實現繼承的,對于你定義的每一個類,python會計算出一個方法解析順序(MRO)列表,這個MRO列表就是一個簡單的所有基類的線性順序列表,例如

>>> F.mro() #等同于F.__mro__
[<class '__main__.F'>, <class '__main__.D'>, <class '__main__.B'>, <class '__main__.E'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>]

?

為了實現繼承,python會在MRO列表上從左到右開始查找基類,直到找到第一個匹配這個屬性的類為止。
而這個MRO列表的構造是通過一個C3線性化算法來實現的。我們不去深究這個算法的數學原理,它實際上就是合并所有父類的MRO列表并遵循如下三條準則:
1.子類會先于父類被檢查
2.多個父類會根據它們在列表中的順序被檢查
3.如果對下一個類存在兩個合法的選擇,選擇第一個父類

九 子類中調用父類的方法

方法一:指名道姓,即父類名.父類方法()

#_*_coding:utf-8_*_
__author__ = 'Linhaifeng'class Vehicle: #定義交通工具類Country='China'def __init__(self,name,speed,load,power):self.name=nameself.speed=speedself.load=loadself.power=powerdef run(self):print('開動啦...')class Subway(Vehicle): #地鐵def __init__(self,name,speed,load,power,line):Vehicle.__init__(self,name,speed,load,power)self.line=linedef run(self):print('地鐵%s號線歡迎您' %self.line)Vehicle.run(self)line13=Subway('中國地鐵','180m/s','1000人/箱','',13)
line13.run()
View Code

方法二:super()

class Vehicle: #定義交通工具類Country='China'def __init__(self,name,speed,load,power):self.name=nameself.speed=speedself.load=loadself.power=powerdef run(self):print('開動啦...')class Subway(Vehicle): #地鐵def __init__(self,name,speed,load,power,line):#super(Subway,self) 就相當于實例本身 在python3中super()等同于super(Subway,self)super().__init__(name,speed,load,power)self.line=linedef run(self):print('地鐵%s號線歡迎您' %self.line)super(Subway,self).run()class Mobike(Vehicle):#摩拜單車passline13=Subway('中國地鐵','180m/s','1000人/箱','',13)
line13.run()
View Code?

強調:二者使用哪一種都可以,但最好不要混合使用?

?

了解部分:

即使沒有直接繼承關系,super仍然會按照mro繼續往后查找

#A沒有繼承B,但是A內super會基于C.mro()繼續往后找
class A:def test(self):super().test()
class B:def test(self):print('from B')
class C(A,B):passc=C()
c.test() #打印結果:from Bprint(C.mro())
#[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]
View Code

指名道姓與super()的區別

#指名道姓
class A:def __init__(self):print('A的構造方法')
class B(A):def __init__(self):print('B的構造方法')A.__init__(self)class C(A):def __init__(self):print('C的構造方法')A.__init__(self)class D(B,C):def __init__(self):print('D的構造方法')B.__init__(self)C.__init__(self)pass
f1=D() #A.__init__被重復調用
'''
D的構造方法
B的構造方法
A的構造方法
C的構造方法
A的構造方法
'''#使用super()
class A:def __init__(self):print('A的構造方法')
class B(A):def __init__(self):print('B的構造方法')super(B,self).__init__()class C(A):def __init__(self):print('C的構造方法')super(C,self).__init__()class D(B,C):def __init__(self):print('D的構造方法')super(D,self).__init__()f1=D() #super()會基于mro列表,往后找
'''
D的構造方法
B的構造方法
C的構造方法
A的構造方法
'''
View Code

當你使用super()函數時,Python會在MRO列表上繼續搜索下一個類。只要每個重定義的方法統一使用super()并只調用它一次,那么控制流最終會遍歷完整個MRO列表,每個方法也只會被調用一次(注意注意注意:使用super調用的所有屬性,都是從MRO列表當前的位置往后找,千萬不要通過看代碼去找繼承關系,一定要看MRO列表

?

轉載于:https://www.cnblogs.com/zhanglin123/p/9268997.html

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

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

相關文章

SpringBoot(十三)-- 不同環境下讀取不同配置

一、場景&#xff1a; 在開發過程中 會使用 開發的一套數據庫&#xff0c;測試的時候 又會使用測試的數據庫&#xff0c;生產環境中 又會切換到生產環境中。常用的方式是 注釋掉一些配置&#xff0c;然后釋放一下配置。SpringBoot提供了在不同環境下切換不同配置的功能&#xf…

MDN文檔基礎知識搜集

Array數組&#xff0c;一種允許你存儲多個值在一個引用里的結構。var myVariable [1,Bob,Steve,10]; 引用數組的元素只需&#xff1a;myVariable[0], myVariable[1], 等等. 發布工具: FTP 客戶端 你還需要一種將文件從本地硬盤上傳到遠程Web服務器的方法。 為了做到這一點&am…

vue-cli生成項目時你應當知道的

一、安裝 npm install -g vue-cli二、創建項目 vue init 模板名 項目名 vue init webpack mymall模板名: 1 . webpack 最常用 2 . webpack-simple // 一個簡單webpackvue-loader的模板&#xff0c;不包含其他功能。 3 . browserify // 一個全面的Browserifyvueify 的模板&am…

es6 --- 正確獲取Generator函數內部的this對象使其可以使用new

首先看2個例子 function * g() {this.a 11; }let o g(); console.log(o.a);可以看見Generator函數里面的this指向的對象取不出來. 再看下一個例子: function* F() {yield this.x 2;yield this.y 3; } new F();可以看出Generator函數無法使用new操作符, 下面一共一個解決…

mysql三-3:完整性約束

閱讀目錄 一 介紹二 not null與default三 unique四 primary key五 auto_increment六 foreign key七 作業一 介紹 約束條件與數據類型的寬度一樣&#xff0c;都是可選參數 作用&#xff1a;用于保證數據的完整性和一致性主要分為&#xff1a; PRIMARY KEY (PK) 標識該字段為該…

LOL

[分享] 從《LOL》談游戲中的隨機動作優化 http://bbs.gameres.com/thread_472292.html 光子工作室陳宇復盤《全民突擊》研發歷程&#xff08;完整版&#xff09; https://mp.weixin.qq.com/s?__bizMjM5OTc2ODUxMw&mid400110877&idx2&sn372fd6492a9d8dd1791d87eb2c…

超級簡易法上傳本地文件到github上

之前文章寫過廖雪峰老師關于git教程的帖子&#xff0c;現在終于有時間實踐了&#xff01;我這段時間在學微信小程序版的貪吃蛇&#xff0c; 想著先把寫好的文件上傳試試&#xff0c;于是乎&#xff0c;便有了如下…… 大家要是不想聽廢話可以拉到最后去…… 1、我先在github…

es6 --- 對任意對象部署可遍歷接口

有時候需要對對象進行遍歷,下面提供一個比較方便的接口, 其基本思路是,首先得到對象的所有鍵(key), 然后將其放在yield* 后面. yield* 可以通過 for … of … 循環遍歷 具體實現如下: function* iterEntries (obj) {let keys Object.keys(obj);for ( let i 0; i < keys.…

element-ui表單驗證:用戶名、密碼、電話、郵箱

之前設計login組件時增加了簡單的表單驗證&#xff0c;因此對應的users組件&#xff0c;添加用戶功能也必須設置相應的驗證規則。 文檔form表單驗證只提供了用戶名/密碼&#xff0c;是否必須/長度限制的驗證。對于電話、郵箱和地址的驗證如下&#xff1a; html部分&#xff0c…

composer(作曲家)安裝php-ml

剛開始我用的是up5.6版本php命令安裝composer 后來使用composer時發現命令行會提示php版本太低 于是我下載了wamp&#xff0c;使用7.1版本的php重新安裝了composer&#xff0c;因為php-ml要求必須是7.1版本 在安裝的時候有一些問題&#xff0c;那就是安裝不成功&#xff0c;并沒…

前端解析返回的對象時json顯示$ref問題的解決

在mapper中寫的語句&#xff0c;結果集中association&#xff0c;采用的一個對象&#xff0c;整個list列表中每個元素有一個對象元素&#xff0c;如果第二個元素中有一個與第一個元素中對象同名的&#xff0c;就會去引用上一個元素的地址&#xff0c;在json前臺解析的時候就不會…

Uncaught TypeError: Cannot redefine property: $router

原因&#xff1a;就如報錯提示所描述的&#xff0c;不能重新定義router&#xff0c;說明是重復定了router&#xff0c;說明是重復定了router&#xff0c;說明是重復定了router。通常是因為在項目中安裝了vue-router的依賴并且用Vue.use()使用了vue-router&#xff0c;還在index…

微信小程序模仿開眼視頻app(一)——視頻首頁、視頻詳情、分類

可到我的github賬號上去copy文件 先展示一下我實現了的功能吧 提示&#xff0c;如果有出現無法加載域名之類問題的的&#xff0c;可以在“設置”-“項目設置”-打鉤“不校驗合法域名……”&#xff1b; 或者直接登錄自己的微信小程序后臺設置域名信息 首頁部分&#xff1a; 1…

es6 --- Thunkify源碼分析

首先看一個例子:讀取package.json下的文件,并將讀取的數據(若讀取失敗)打印出來 // 導入fs和thunkify模塊 var thunkify require(thunkify); var fs require(fs);// 定義讀取文件的函數read var read thunkify(fs.readFile);// 調用read函數讀取package.json下的文件.并對數…

(轉)C# WebApi 身份認證解決方案:Basic基礎認證

原文地址&#xff1a;http://www.cnblogs.com/landeanfen/p/5287064.html 閱讀目錄 一、為什么需要身份認證二、Basic基礎認證的原理解析 1、常見的認證方式2、Basic基礎認證原理三、Basic基礎認證的代碼示例 1、登錄過程2、/Home/Index主界面3、WebApiCORS驗證部分&#xff08…

commit之后,想撤銷commit

git reset --soft HEAD^轉載于:https://www.cnblogs.com/gjack/p/9271556.html

ZNZD平臺vue項目

一、安裝配置node.js 1.1 配置企業級軟件倉庫 1&#xff09;首先用的是Nexus Repository Manager搭建npm私服&#xff1b;&#xff08;待補充&#xff09; 2&#xff09;項目使用修改.npmrc文件來修改源 現在需要做的就是修改源&#xff01;采取配置npmrc文件的方式&#x…

微信小程序模仿開眼視頻app(二)——搜索功能

微信小程序模仿開眼視頻app&#xff08;一&#xff09;有介紹首頁、視頻詳情和分類部分 可到我的github賬號上去copy文件 搜索部分 一開始沒想要設置歷史記錄啊、熱門搜索啊這些的&#xff0c;只是想把搜索框弄好看一點&#xff0c;無意中發現了微信官方ui庫&#xff1a;weu…

es6 --- Thunk函數的作用

首先了解一下javascript里面的Thunk函數的含義:將多參數函數,替換成一個只接受回調函數作為參數的單參數函數 // 一個具體的例子// 正常版本的readFile(多參數函數) fs.readFile(filename, callback);// Thunk版本的readFile(單參數版本) var Thunk function (fileName) {ret…

設計模式(六)------設計模式六大原則(5):迪米特法則

轉載自&#xff1a;http://www.jianshu.com/p/14589fb6978e &#xff08;作者簡書&#xff1a;涅槃1992&#xff09; 揭秘迪米特法則 迪米特法則&#xff08;Law of demeter,縮寫是LOD&#xff09;要求&#xff1a;一個對象應該對其他對象保持最少了解&#xff0c; 通縮的講就是…