Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 久久精品人人做人人爽97,国产又黄又爽又色视频免费观看 ,一级毛片免费毛片一级毛片免费

          整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          「Medium 萬贊好文」ViewModel 和 L

          「Medium 萬贊好文」ViewModel 和 LIveData:模式 + 反模式

          文作者: https://medium.com/@JoseAlcerreca

          原文地址: https://medium.com/androiddevelopers/viewmodels-and-livedata-patterns-antipatterns-21efaef74a54

          譯者:秉心說

          View 和 ViewModel

          分配責任

          理想情況下,ViewModel 應該對 Android 世界一無所知。這提升了可測試性,內存泄漏安全性,并且便于模塊化。通常的做法是保證你的 ViewModel 中沒有導入任何 android.*,android.arch.* (譯者注:現在應該再加一個 androidx.lifecycle)除外。這對 Presenter(MVP) 來說也一樣。

          ? 不要讓 ViewModel 和 Presenter 接觸到 Android 框架中的類

          條件語句,循環和通用邏輯應該放在應用的 ViewModel 或者其它層來執行,而不是在 Activity 和 Fragment 中。View 通常是不進行單元測試的,除非你使用了 http://robolectric.org/,所以其中的代碼越少越好。View 只需要知道如何展示數據以及向 ViewModel/Presenter 發送用戶事件。這叫做 https://martinfowler.com/eaaDev/PassiveScreen.html 模式。

          ? 讓 Activity/Fragment 中的邏輯盡量精簡

          ViewModel 中的 View 引用

          https://developer.android.com/topic/libraries/architecture/viewmodel.html 和 Activity/Fragment具有不同的作用域。當 Viewmodel 進入 alive 狀態且在運行時,activity 可能位于 https://developer.android.com/guide/components/activities/activity-lifecycle.html 的任何狀態。Activitie 和 Fragment 可以在 ViewModel 無感知的情況下被銷毀和重新創建。

          向 ViewModel 傳遞 View(Activity/Fragment) 的引用是一個很大的冒險。假設 ViewModel 請求網絡,稍后返回數據。若此時 View 的引用已經被銷毀,或者已經成為一個不可見的 Activity。這將導致內存泄漏,甚至 crash。

          ? 避免在 ViewModel 中持有 View 的引用

          在 ViewModel 和 View 中通信的建議方式是觀察者模式,使用 LiveData 或者其他類庫中的可觀察對象。

          觀察者模式

          在 Android 中設計表示層的一種非常方便的方法是讓 View 觀察和訂閱 ViewModel(中的變化)。由于 ViewModel 并不知道 Android 的任何東西,所以它也不知道 Android 是如何頻繁的殺死 View 的。這有如下好處:

          1. ViewModel 在配置變化時保持不變,所以當設備旋轉時不需要再重新請求資源(數據庫或者網絡)。
          2. 當耗時任務執行結束,ViewModel 中的可觀察數據更新了。這個數據是否被觀察并不重要,嘗試更新一個
          3. 不存在的 View 并不會導致空指針異常。
          4. ViewModel 不持有 View 的引用,降低了內存泄漏的風險。
          private void subscribeToModel() {
           // Observe product data
           viewModel.getObservableProduct().observe(this, new Observer<Product>() {
           @Override
           public void onChanged(@Nullable Product product) {
           mTitle.setText(product.title);
           }
           });
          }
          

          ? 讓 UI 觀察數據的變化,而不是把數據推送給 UI

          胖 ViewModel

          無論是什么讓你選擇分層,這總是一個好主意。如果你的 ViewModel 擁有大量的代碼,承擔了過多的責任,那么:

          • 移除一部分邏輯到和 ViewModel 具有同樣作用域的地方。這部分將和應用的其他部分進行通信并更新
          • ViewModel 持有的 LiveData。
          • 采用 https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html,添加一個 domain 層。這是一個可測試,易維護的架構。https://github.com/android/architecture-samples 中有 Clean Architecture 的示例。

          ? 分發責任,如果需要的話,添加 domain 層

          使用數據倉庫

          如 https://developer.android.com/jetpack/docs/guide 中所說,大部分 App 有多個數據源:

          1. 遠程:網絡或者云端
          2. 本地:數據庫或者文件
          3. 內存緩存

          在你的應用中擁有一個數據層是一個好主意,它和你的視圖層完全隔離。保持緩存和數據庫與網絡同步的算法并不簡單。建議使用單獨的 Repository 類作為處理這種復雜性的單一入口點.

          如果你有多個不同的數據模型,考慮使用多個 Repository 倉庫。

          ? 添加數據倉庫作為你的數據的單一入口點。

          處理數據狀態

          考慮下面這個場景:你正在觀察 ViewModel 暴露出來的一個 LiveData,它包含了需要顯示的列表項。那么 View 如何區分數據已經加載,網絡錯誤和空集合?

          • 你可以通過 ViewModel 暴露出一個 LiveData ,MyDataState 可以包含數據正在加載,已經加載完成,發生錯誤等信息。
          • 你可以將數據包裝在具有狀態和其他元數據(如錯誤消息)的類中。查看示例中的 https://developer.android.com/jetpack/docs/guide#addendum 類。

          ? 使用包裝類或者另一個 LiveData 來暴露數據的狀態信息

          保存 activity 狀態

          當 activity 被銷毀或者進程被殺導致 activity 不可見時,重新創建屏幕所需要的信息被稱為 activity 狀態。屏幕旋轉就是最明顯的例子,如果狀態保存在 ViewModel 中,它就是安全的。

          但是,你可能需要在 ViewModel 也不存在的情況下恢復狀態,例如當操作系統由于資源緊張殺掉你的進程時。

          為了有效的保存和恢復 UI 狀態,使用 onSaveInstanceState() 和 ViewModel 組合。

          詳見:[ViewModels: Persistence, onSaveInstanceState(), Restoring UIState and Loaders](https://medium.com/google-developers/viewmodels-persistence-onsaveinstancestate-restoring-ui-state-and-loaders-fc7cc4a6c090) 。

          Event

          Event 指只發生一次的事件。ViewModel 暴露出的是數據,那么 Event 呢?例如,導航事件或者展示 Snackbar 消息,都是應該只被執行一次的動作。

          LiveData 保存和恢復數據,和 Event 的概念并不完全符合。看看具有下面字段的一個 ViewModel:

          LiveData<String> snackbarMessage=new MutableLiveData<>();
          

          Activity 開始觀察它,當 ViewModel 結束一個操作時需要更新它的值:

          snackbarMessage.setValue("Item saved!");
          

          Activity 接收到了值并且顯示了 SnackBar。顯然就應該是這樣的。

          但是,如果用戶旋轉了手機,新的 Activity 被創建并且開始觀察。當對 LiveData 的觀察開始時,新的 Activity 會立即接收到舊的值,導致消息再次被顯示。

          與其使用架構組件的庫或者擴展來解決這個問題,不如把它當做設計問題來看。我們建議你把事件當做狀態的一部分。

          把事件設計成狀態的一部分。更多細節請閱讀 https://medium.com/google-developers/livedata-with-snackbar-navigation-and-other-events-the-singleliveevent-case-ac2622673150

          ViewModel 的泄露

          得益于方便的連接 UI 層和應用的其他層,響應式編程在 Android 中工作的很高效。LiveData 是這個模式的關鍵組件,你的 Activity 和 Fragment 都會觀察 LiveData 實例。

          LiveData 如何與其他組件通信取決于你,要注意內存泄露和邊界情況。如下圖所示,視圖層(Presentation Layer)使用觀察者模式,數據層(Data Layer)使用回調。

          當用戶退出應用時,View 不可見了,所以 ViewModel 不需要再被觀察。如果數據倉庫 Repository 是單例模式并且和應用同作用域,那么直到應用進程被殺死,數據倉庫 Repository 才會被銷毀。 只有當系統資源不足或者用戶手動殺掉應用這才會發生。如果數據倉庫 Repository 持有 ViewModel 的回調的引用,那么 ViewModel 將會發生內存泄露。

          如果 ViewModel 很輕量,或者保證操作很快就會結束,這種泄露也不是什么大問題。但是,事實并不總是這樣。理想情況下,只要沒有被 View 觀察了,ViewModel 就應該被釋放。

          你可以選擇下面幾種方式來達成目的:

          • 通過 ViewModel.onCLeared() 通知數據倉庫釋放 ViewModel 的回調
          • 在數據倉庫 Repository 中使用 弱引用 ,或者 Event Bu(兩者都容易被誤用,甚至被認為是有害的)。
          • 通過在 View 和 ViewModel 中使用 LiveData 的方式,在數據倉庫和 ViewModel 之間進程通信

          ? 考慮邊界情況,內存泄露和耗時任務會如何影響架構中的實例。

          ? 不要在 ViewModel 中進行保存狀態或者數據相關的核心邏輯。 ViewModel 中的每一次調用都可能是最后一次操作。

          數據倉庫中的 LiveData

          為了避免 ViewModel 泄露和回調地獄,數據倉庫應該被這樣觀察:

          當 ViewModel 被清除,或者 View 的生命周期結束,訂閱也會被清除:

          如果你嘗試這種方式的話會遇到一個問題:如果不訪問 LifeCycleOwner 對象的話,如果通過 ViewModel 訂閱數據倉庫?使用 https://developer.android.com/topic/libraries/architecture/livedata#transform_livedata 可以很方便的解決這個問題。Transformations.switchMap 可以讓你根據一個 LiveData 實例的變化創建新的 LiveData。它還允許你通過調用鏈傳遞觀察者的生命周期信息:

          LiveData<Repo> repo=Transformations.switchMap(repoIdLiveData, repoId -> {
           if (repoId.isEmpty()) {
           return AbsentLiveData.create();
           }
           return repository.loadRepo(repoId);
           }
          );
          

          在這個例子中,當觸發更新時,這個函數被調用并且結果被分發到下游。如果一個 Activity 觀察了 repo,那么同樣的 LifecycleOwner 將被應用在 repository.loadRepo(repoId) 的調用上。

          無論什么時候你在 https://developer.android.com/reference/android/arch/lifecycle/ViewModel.html 內部需要一個 https://developer.android.com/reference/android/arch/lifecycle/Lifecycle.html 對象時,https://developer.android.com/topic/libraries/architecture/livedata#transform_livedata 都是一個好方案。

          繼承 LiveData

          在 ViewModel 中使用 LiveData 最常用的就是 MutableLiveData,并且將其作為 LiveData 暴露給外部,以保證對觀察者不可變。

          如果你需要更多功能,繼承 LiveData 會讓你知道活躍的觀察者。這對你監聽位置或者傳感器服務很有用。

          public class MyLiveData extends LiveData<MyData> {
           public MyLiveData(Context context) {
           // Initialize service
           }
           @Override
           protected void onActive() {
           // Start listening
           }
           @Override
           protected void onInactive() {
           // Stop listening
           }
          }
          

          什么時候不要繼承 LiveData

          你也可以通過 onActive() 來開啟服務加載數據。但是除非你有一個很好的理由來說明你不需要等待 LiveData 被觀察。下面這些通用的設計模式:

          • 給 ViewModel 添加 start() 方法,并盡快調用它。https://github.com/android/architecture-samples/blob/dev-todo-mvvm-live/todoapp/app/src/main/java/com/example/android/architecture/blueprints/todoapp/addedittask/AddEditTaskFragment.java#L64]
          • 設置一個觸發加載的屬性 https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample/app/src/main/java/com/android/example/github/ui/repo/RepoFragment.kt]

          你并不需要經常繼承 LiveData 。讓 Activity 和 Fragment 告訴 ViewModel 什么時候開始加載數據。

          分割線

          翻譯就到這里了,其實這篇文章已經在我的收藏夾里躺了很久了。最近 Google 重寫了 https://github.com/android/plaid 應用,用上了一系列最新技術棧, https://developer.android.com/topic/libraries/architecture/,MVVM, Kotlin,協程 等等。這也是我很喜歡的一套技術棧,之前基于此開源了 https://github.com/lulululbj/wanandroid 應用 ,詳見 https://juejin.im/post/5cb473e66fb9a068af37a6ce 。

          當時基于對 MVVM 的淺薄理解寫了一套自認為是 MVVM 的 MVVM 架構,在閱讀一些關于架構的文章,以及 Plaid 源碼之后,發現了自己的 MVVM 的一些認知誤區。后續會對 https://github.com/lulululbj/wanandroid 應用進行合理改造,并結合上面譯文中提到的知識點作一定的說明。歡迎 Star !

          網站開發過程中,需要從前端向后端傳入數據,由后端對數據進行操作,比如計算、存入數據庫等。

          從前端向后端傳輸數據,一般使用form表單。在Django中,有三種方法:

          1. 手寫前端html代碼,使用form表單:
          <form action=’’method=’post’> </form>
          1. Django提供了form類,生成form表單。
          2. Django提供了Modelform類,生成form表單。

          Modelform做為Django中集成的組件,主要針對數據庫中的某個表操作,通過models.py關聯數據庫。

          本文著重講modelform的使用,下面正式開始。

          首先建立一個forms.py,用來寫項目里的表單類。

          首先引入幾個類

          from django import forms #引入forms表單類
          from users.models import User #引入models里的User類
          from django.core.exceptions import ValidationError #引入異常拋出類

          創建User表單類,類繼承了forms.ModelForm,password_confirm是密碼確認,我們在進行注冊的時候,往往會要求確認一次密碼。

          class Meta:是利用model創建表單的類。model=User,用來實例化models.py中的User類,fields是表單中的字段,也就是表單項目。widgets是一個字典,在這里定義password表單為密碼輸入格式。

          class UserModelForm(forms.ModelForm):
              password_confirm=forms.CharField(label="確認密碼",widget=forms.PasswordInput,min_length=6,max_length=20)
              class Meta:
                  model=User
                  fields=['username','password','password_confirm','gender','role']
                  widgets={"password":forms.PasswordInput()}

          下面在templates文件夾下建立一個user_add_form.html文件,用來展示表單。

          在views.py中增加一個方法user_add_form()方法。該方法需要使用forms.py中的UserModelForm類和models中的User類,在頭部引入這兩個類,

          from users.models import User   #引入models里的User類
          from users.forms import UserModelForm #引入forms里的UserModelForm

          增加一個user_add_form(request)方法,當前端的request是一個get方法時,實例化UserModelForm(),返回render方法,顯示form表單,否則,將request.POST的數據傳入UserModelForm類并實例化,

          def user_add_form(request):
              if request.method=="GET":
                  form=UserModelForm()
              return render(request,"user_add_form.html",{"form":form})

          在urls.py中增加一個路由。

          在user_add_form.html中寫入{{form}},用來展示后端返回的form數據。

          下面在瀏覽中測試一下。

          輸入127.0.0.1:8000/user_add_form/

          右鍵檢查頁面源碼,發現,字段及輸入框已經在頁面中。

          本文結束。下一篇文章,將對user_add_form.html進行修改,實現表單的輸入功能,并通過表單將數據傳入后端,并插入數據庫。

          前面幾期內容連續的介紹了Python的函數相關編程知識,是一個相對且完整的知識域,本文主要是對函數知識的一些有益拓展和補充。

          本文簡單扼要地說,輔以代碼進一步地加深理解。我們繼續——記得點贊+關注@傳新視界

          函數進階與補充

          遞歸函數

          當函數調用自身而生成最終結果時,這樣的函數稱為遞歸。有時遞歸函數非常有用,因為它們使編寫代碼變得更容易——使用遞歸范式編寫一些算法非常容易,而其他算法則不是這樣。沒有不能以迭代方式重寫的遞歸函數,換句話說,所有遞歸函數都可以通過循環迭代的方式實現,因此通常由程序員根據手頭的情況選擇最佳方法。

          遞歸函數主體通常有兩個部分:一部分的返回值依賴于對自身的后續調用,另一部分的返回值不依賴于對自身的后續調用(稱基本情況,或遞歸邊界)。

          作為理解的參考示例,我們看一個階乘函數N!作為遞歸的兩部分分別是:基本情況(邊界,用來結束遞歸)是當N為0或1時,函數返回1,不需要進一步計算。另一方面,在一般情況下的自我調用,即N!返回的生成結果:

          1 * 2 * ... * (N-1) * N

          如果你仔細想想,N!可以寫成這樣:N!=(N - 1) !*N。作為一個實際的例子,請看如下的階乘表示:

          5!=1 * 2 * 3 * 4 * 5=(1 * 2 * 3 * 4) * 5=4! * 5

          我們來轉化成函數實現:

          # 階乘遞歸函數實現
          def factorial(n):
              if n in (0, 1): # 遞歸邊界
                  return 1
              return factorial(n - 1) * n # 遞歸調用
          

          高手大俠們在編寫算法時經常使用遞歸函數,編寫遞歸函數非常有趣。作為練習,嘗試使用遞歸和迭代方法解決幾個簡單的問題。很好的練習對象可能是計算斐波那契數列,或其它諸如此類的東西。自己動手去試試吧。

          提示:

          在編寫遞歸函數時,總是考慮要進行多少個嵌套調用,因為這是有限制的。有關這方面的更多信息,請查看sys.getrecursionlimit()和sys.setrecursionlimit()。

          匿名函數

          還有一種函數是匿名函數(Anonymous functions)。這些函數在Python中稱為lambda(蘭姆達),其通常在使用具有自己完整定義名稱的函數有些多余時而使用,此時所需要的只是一個快速、簡單的一行程序來完成這項工作。

          假設我們想要一個列表,所有N的某個值,是5的倍數的數字。為此,我們可以使用filter()函數,它需要一個函數和一個可迭代對象作為輸入。返回值是一個過濾器對象,當你遍歷它時,會從輸入可迭代對象中生成元素,所需的參數函數會為其返回True。如果不使用匿名函數,我們可能會這樣做:

          def isMultipleOfFive(n):
              return not n % 5
          
          def getMultiplesOfFive(n):
              return list(filter(isMultipleOfFive, range(n)))
          

          注意我們如何使用isMultipleOfFive()來過濾前n個自然數。這似乎有點過分——任務及其很簡單,我們不需要為其他任何事情保留isMultipleOfFive()函數。此時,我們就可用lambda函數來重寫它:

          # lambda過濾
          def getMultiplesOfFive(n):
               return list(filter(lambda k: not k % 5, range(n)))
          

          邏輯是完全相同的,但是過濾函數現在是個lambda函數,顯然,Lambda更簡單。

          定義Lambda函數非常簡單,它遵循以下形式:

          funcName=lambda [parameter_list]: expression

          其返回的是一個函數對象,相當于:

          def func_ name([parameter_list]):return expression

          參數列表以逗號分隔。

          注意,可選參數是方括號括起來的部分,是通用語法的表示形式,即文中的方括號部分是可選的,根據實際需要提供,

          我們再來看另外兩個等價函數的例子,以兩種形式定義:

          # lambda說明
          # 示例 1: 兩數相加
          def adder(a, b):
              return a + b
          # 等價于:
          adder_lambda=lambda a, b: a + b
          
          # 示例 2: 字符串轉大寫
          def to_upper(s):
              return s.upper()
          # 等價于:
          to_upper_lambda=lambda s: s.upper()
          

          前面的例子非常簡單。第一個函數將兩個數字相加,第二個函數生成字符串的大寫版本。注意,我們將lambda表達式返回的內容賦值給一個名稱(adder_lambda, to_upper_lambda),但是當按照filter()示例中的方式使用lambda時,就不需要這樣做了——不需要把匿名函數賦給變量。

          函數屬性

          Python中每個函數都是一個完整的對。因此,它有許多屬性。其中一些是特殊的,可以以內省的方式在運行時檢查函數對象。下面的示例,展示了它們的一部分以及如何為示例函數顯示它們的值:

          # 函數屬性
          def multiplication(a, b=1):
              """返回a乘以b的結構. """
              return a * b
          
          if __name__=="__main__":
              special_attributes=[
              "__doc__", "__name__", "__qualname__", "__module__",
              "__defaults__", "__code__", "__globals__", "__dict__",
              "__closure__", "__annotations__", "__kwdefaults__",
              ]
              for attribute in special_attributes:
                  print(attribute, '->', getattr(multiplication, attribute))
          

          我們使用內置的getattr()函數來獲取這些屬性的值。getattr(obj, attribute)等價于obj.attribute,當我們需要在運行時動態地獲取屬性時,就從變量中獲取屬性的名稱(如本例中所示),此時它就會派上用場。

          運行這個腳本會得到類似如下輸出:

          __doc__ -> 返回a乘以b的結果.

          __name__ -> multiplication

          __qualname__ -> multiplication

          __module__ -> __main__

          __defaults__ -> (1,)

          __code__ -> <……>

          __globals__ -> {…略…}

          __dict__ -> {}

          __closure__ -> None

          __annotations__ -> {}

          __kwdefaults__ -> None

          這里省略了__globals__屬性的值,內容太多。這個屬性的含義可以在Python數據模型文檔頁面(或自帶幫助文檔中)的可調用類型部分找到:

          https://docs.python.org/3/reference/datamodel.html#the-standard-typehierarchy

          再次提醒:如果你想查看對象的所有屬性,只需調用dir(object_name),將得到其所有屬性的列表

          內置函數

          Python自帶很多內置函數。它們可以在任何地方使用,你可以通過dir(__builtins__)來查看builtins模塊,或通過訪問官方Python文檔來獲得它們的列表。這里就不一一介紹了。在前面的學習過程中,我們已經見過其中的一些,如any、bin、bool、divmod、filter、float、getattr、id、int、len、list、min、print、set、tuple、type和zip等,但還有更多,建議你至少應該閱讀一次。熟悉它們,嘗試它們,為它們每個編寫一小段代碼,并確保您隨時可以使用它們,以便在需要時使用它們。

          可在官方文檔中找到這個內置函數列表:https://docs.python.org/3/library/functions.html 。

          文檔化代碼

          我們非常喜歡不需要文檔的代碼。當我們正確地編程、選擇正確的名稱、并注意細節時,代碼應該是不言自明的,幾乎不需要文檔。不過,有時注釋非常有用,添加一些文檔化描述也是如此。你可以在Python的PEP 257規范——文檔字符串約定中找到Python的文檔指南:

          https://www.python.org/dev/peps/pep-0257/,

          但在這里還是會向你展示基本原理。Python的文檔中包含字符串,這些字符串被恰當地稱為文檔字符串(docstrings)。任何對象都可以被文檔化來加以描述記錄,可以使用單行或多行文檔字符串。單行程序非常簡單。不是為函數提供另外的簽名,而應該聲明或描述函數的目的。請看下面的示例:

          # 簡單的文檔化代碼
          def square(n):
              """功能:返回數字n的平方。 """
              return n ** 2
          
          def get_username(userid):
              """功能:返回給定id的用戶名稱。 """
              return db.get(user_id=userid).username
          
          • 使用三重雙引號字符串可以在以后輕松展開或擴展文檔內容。
          • 使用以句號結尾的句子,不要在前后留下空行。
          • 多行注釋的結構與此類似。應該用一行代碼簡單地說明對象的主旨,然后是更詳細的描述。

          作為多行文檔化的一個例子,我們在下面的例子中使用Sphinx表示法記錄了一個虛構的connect()函數及文檔化描述:

          # 多行文檔化代碼
          def connect(host, port, user, password):
              """功能:連接數據庫并返回連接對象.
              使用如下參數直接連接 PostgreSQL數據庫.
              :param host: 主機 IP.
              :param port: 端口.
              :param user: 連接用戶名.
              :param password: 連接密碼.
              :return: 連接對象.
              """
              # 函數主體...
              return connection

          提示:

          Sphinx是用于創建Python文檔的最廣泛使用的工具之一——事實上,官方Python文檔就是用它編寫的。絕對值得花點時間去看看。

          內置函數help()用于即時交互使用的,它就使用對象的文檔字符串為對象創建文檔頁面來展示對象的用法。基本用法如下:

          def square(n):
              """功能:返回數字n的平方。 """
              return n ** 2
          
          help(square)
          Help on function square in module __main__:
          
          square(n)
          功能:返回數字n的平方。

          首先明確或定義一個對象或函數(包括已有的對象或函數),然后使用內置help函數,并把對象或函數做help的參數,該函數就會返回相應對象的說明文檔了。就這么簡單。

          本文小結

          本文主要基于Python語言的一大特色——函數來拓展的一些相關編程知識,包括遞歸函數(重點是有限性和邊界性)、lambda函數(簡潔性和臨時性)以及函數的屬性以及如何實現函數的文檔化描述等。

          本文就寫這些了,記得點贊 +關注@傳新視界,轉發分享給更多的朋友。再見^_^


          主站蜘蛛池模板: 午夜视频一区二区三区| 动漫精品专区一区二区三区不卡 | 日本免费一区二区三区最新vr| 鲁丝丝国产一区二区| 精品亚洲一区二区| 偷拍精品视频一区二区三区| 性盈盈影院免费视频观看在线一区| 国产在线aaa片一区二区99| 一区二区国产在线观看| 无码视频一区二区三区| 亚洲色偷精品一区二区三区| 国产在线一区二区| 亚洲综合国产一区二区三区| 久久国产精品一区| 国产激情一区二区三区 | 福利一区国产原创多挂探花| 日韩毛片一区视频免费| 国产一国产一区秋霞在线观看| 精品国产高清自在线一区二区三区 | 亚洲日本一区二区| 中文字幕日韩一区二区三区不| 久久国产精品一区| 国产成人无码一区二区三区在线| 亚洲熟妇av一区二区三区漫画| 伊人久久精品无码av一区| 国产午夜精品一区二区三区嫩草| 精品亚洲一区二区| 久久精品亚洲一区二区三区浴池| 蜜桃无码AV一区二区| 亚洲欧美日韩一区二区三区在线 | 国产精品美女一区二区| 国产亚洲福利精品一区二区| 一区二区三区在线观看中文字幕| 风流老熟女一区二区三区| 人妻无码一区二区视频| 中文字幕亚洲乱码熟女一区二区 | 一区二区在线免费观看| 日韩精品一区在线| 日韩精品一区二区三区中文版 | 国产乱码精品一区二区三区 | 91麻豆精品国产自产在线观看一区|