diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..503b3fa0f71302263a5bc1bbb64a1af9e5d811a4 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,6 @@ +repos: + - repo: git@codechina.csdn.net:csdn/skill_tree_hook.git + rev: 8cb76ab3b493582d3dab0021fb6fddfa28ec5a66 + hooks: + - id: pre-commit + verbose: true \ No newline at end of file diff --git "a/data/1..NET\345\210\235\351\230\266/2.C#\350\257\255\346\263\225/3.C#\345\255\227\347\254\246\344\270\262\346\240\274\345\274\217\350\256\276\347\275\256/StringFormatting.md" "b/data/1..NET\345\210\235\351\230\266/2.C#\350\257\255\346\263\225/3.C#\345\255\227\347\254\246\344\270\262\346\240\274\345\274\217\350\256\276\347\275\256/StringFormatting.md" index cd5809d9fe94cbd27cabbfd500b0becd6aea5b3c..65bf2a98ec216521b1205eb95f3a36a9e00da486 100644 --- "a/data/1..NET\345\210\235\351\230\266/2.C#\350\257\255\346\263\225/3.C#\345\255\227\347\254\246\344\270\262\346\240\274\345\274\217\350\256\276\347\275\256/StringFormatting.md" +++ "b/data/1..NET\345\210\235\351\230\266/2.C#\350\257\255\346\263\225/3.C#\345\255\227\347\254\246\344\270\262\346\240\274\345\274\217\350\256\276\347\275\256/StringFormatting.md" @@ -1,8 +1,10 @@ -# 在C#中执行基本字符串格式设置 +# 鍦–#涓墽琛屽熀鏈瓧绗︿覆鏍煎紡璁剧疆 -System.String是一个类,专门用于存储字符串,允许对字符串进行许多操作。由于这种数据类型非常重要,C#提供了它自己的关键字和相关的语法,以便于使用这个类来轻松地处理字符串。 String源码网址: https://referencesource.microsoft.com/#mscorlib/system/string.cs +System.String鏄竴涓被锛屼笓闂ㄧ敤浜庡瓨鍌ㄥ瓧绗︿覆锛屽厑璁稿瀛楃涓茶繘琛岃澶氭搷浣溿傜敱浜庤繖绉嶆暟鎹被 +鍨嬮潪甯搁噸瑕侊紝C#鎻愪緵浜嗗畠鑷繁鐨勫叧閿瓧鍜岀浉鍏崇殑璇硶锛屼互渚夸簬浣跨敤杩欎釜绫绘潵杞绘澗鍦板鐞嗗瓧绗︿覆銆 +String 婧愮爜缃戝潃: https://referencesource.microsoft.com/#mscorlib/system/string.cs -使用运算符重载可以连接字符串: +浣跨敤杩愮畻绗﹂噸杞藉彲浠ヨ繛鎺ュ瓧绗︿覆: ```csharp string message1 = "Hello"; // return "Hello" @@ -10,34 +12,34 @@ message1 += ", CodeChina"; // return "Hello, CodeChina" string message2 = message1 + "!"; //return "Hello, CodeChina!" ``` -C#还允许使用类似于索引器的语法来提取指定的字符: +C#杩樺厑璁镐娇鐢ㄧ被浼间簬绱㈠紩鍣ㄧ殑璇硶鏉ユ彁鍙栨寚瀹氱殑瀛楃: ```csharp string message1 = "Hello"; char char1 = message[1] // return 'e' ``` -这个类可以完成许多常见的任务,如替换字符、删除空白和把字母变成大写形式等等。可用的方法如下表所示(此表并不完整,只介绍部分字符串提供的常用功能)。 +杩欎釜绫诲彲浠ュ畬鎴愯澶氬父瑙佺殑浠诲姟锛屽鏇挎崲瀛楃銆佸垹闄ょ┖鐧藉拰鎶婂瓧姣嶅彉鎴愬ぇ鍐欏舰寮忕瓑绛夈傚彲鐢ㄧ殑鏂规硶濡備笅琛ㄦ墍绀(姝よ〃骞朵笉瀹屾暣锛屽彧浠嬬粛閮ㄥ垎瀛楃涓叉彁渚涚殑甯哥敤鍔熻兘)銆 -|方法|作用| +|鏂规硶|浣滅敤| |----|----| -|Compare|比较字符串的内容,判断某些字符是否相等| -|Concat |把多个字符串实例合并为一个实例| -|Format |格式化包含各种值的字符串和如何格式化每个值的说明符| -|IndexOf|定位字符串中第一次出现某个给定子字符串或字符的位置| -|Insert |把一个字符串实例插入到另一个字符串实例的指定索引处| -|Join |合并字符串数组,创建一个新字符串| -|PadLeft|在字符串的左侧,通过添加指定的重复字符填充字符串| -|Replace|用另一个字符或子字符串替换字符串中给定的字符或子字符串| -|Split |在出现给定字符的地方,把字符串拆分为一个字符串数组| -|Substring|在字符串中检索给定位置的子字符串| -|ToLower|把字符串转换为小写形式| -|ToUpper|把字符串转换为大写形式| -|Trim |删除首位的空白| - ->注意如果Format想要输出'{'或'}',请这样string.Format("{{Hello}}"); - -除了这些方法C#还提供了'@'和'$',@是可以忽略字符串的转义,$是可以把代码插到字符串中。 +|Compare|姣旇緝瀛楃涓茬殑鍐呭锛屽垽鏂煇浜涘瓧绗︽槸鍚︾浉绛墊 +|Concat |鎶婂涓瓧绗︿覆瀹炰緥鍚堝苟涓轰竴涓疄渚媩 +|Format |鏍煎紡鍖栧寘鍚悇绉嶅肩殑瀛楃涓插拰濡備綍鏍煎紡鍖栨瘡涓肩殑璇存槑绗 +|IndexOf|瀹氫綅瀛楃涓蹭腑绗竴娆″嚭鐜版煇涓粰瀹氬瓙瀛楃涓叉垨瀛楃鐨勪綅缃畖 +|Insert |鎶婁竴涓瓧绗︿覆瀹炰緥鎻掑叆鍒板彟涓涓瓧绗︿覆瀹炰緥鐨勬寚瀹氱储寮曞| +|Join |鍚堝苟瀛楃涓叉暟缁勶紝鍒涘缓涓涓柊瀛楃涓瞸 +|PadLeft|鍦ㄥ瓧绗︿覆鐨勫乏渚э紝閫氳繃娣诲姞鎸囧畾鐨勯噸澶嶅瓧绗﹀~鍏呭瓧绗︿覆| +|Replace|鐢ㄥ彟涓涓瓧绗︽垨瀛愬瓧绗︿覆鏇挎崲瀛楃涓蹭腑缁欏畾鐨勫瓧绗︽垨瀛愬瓧绗︿覆| +|Split |鍦ㄥ嚭鐜扮粰瀹氬瓧绗︾殑鍦版柟锛屾妸瀛楃涓叉媶鍒嗕负涓涓瓧绗︿覆鏁扮粍| +|Substring|鍦ㄥ瓧绗︿覆涓绱㈢粰瀹氫綅缃殑瀛愬瓧绗︿覆| +|ToLower|鎶婂瓧绗︿覆杞崲涓哄皬鍐欏舰寮弢 +|ToUpper|鎶婂瓧绗︿覆杞崲涓哄ぇ鍐欏舰寮弢 +|Trim |鍒犻櫎棣栦綅鐨勭┖鐧絴 + +>娉ㄦ剰濡傛灉Format鎯宠杈撳嚭'{'鎴'}',璇疯繖鏍穝tring.Format("{{Hello}}"); + +闄や簡杩欎簺鏂规硶C#杩樻彁渚涗簡'@'鍜'$'锛孈鏄彲浠ュ拷鐣ュ瓧绗︿覆鐨勮浆涔夛紝$鏄彲浠ユ妸浠g爜鎻掑埌瀛楃涓蹭腑銆 ```csharp int count = 6; @@ -45,9 +47,9 @@ string str1 = $"6{count}6"; // return "666" string str2 = @"6\r6\n6"; //return "6\r6\n6" ``` -以下程序中,不能使str3等于`"Hello, CodeChina!"`的是: +浠ヤ笅绋嬪簭涓紝涓嶈兘浣縮tr3绛変簬`"Hello, CodeChina!"`鐨勬槸锛 -## 答案 +## 绛旀 ```csharp var str1 = "Hello, "; @@ -55,7 +57,7 @@ var str2 = "CodeChina!"; var str3 = "str1" + "str2"; ``` -## 选项 +## 閫夐」 ### A @@ -81,26 +83,26 @@ var str2 = "CodeChina!"; var str3 = string.Concat(str1, str2); ``` -|格式说明符|应用|含义|示例| +|鏍煎紡璇存槑绗搴旂敤|鍚箟|绀轰緥| |----------|----|----|----| -|C|数字类型|特定地区的货币值|$666.00| -|D|用于数字类型|一般的整数|666| -|E|数字类型|科学计数法|6.660000E+002| -|F|数字类型|小数点后的位数固定|666.00| -|G|数字类型|一般的数字|666| -|N|数字类型|通常是特定地区的数字格式|666.00| -|P|数字类型|百分比计数法|66,600.00%| -|X|只用于整数类型|十六进制格式|29A| +|C|鏁板瓧绫诲瀷|鐗瑰畾鍦板尯鐨勮揣甯佸紎$666.00| +|D|鐢ㄤ簬鏁板瓧绫诲瀷|涓鑸殑鏁存暟|666| +|E|鏁板瓧绫诲瀷|绉戝璁℃暟娉晐6.660000E+002| +|F|鏁板瓧绫诲瀷|灏忔暟鐐瑰悗鐨勪綅鏁板浐瀹殀666.00| +|G|鏁板瓧绫诲瀷|涓鑸殑鏁板瓧|666| +|N|鏁板瓧绫诲瀷|閫氬父鏄壒瀹氬湴鍖虹殑鏁板瓧鏍煎紡|666.00| +|P|鏁板瓧绫诲瀷|鐧惧垎姣旇鏁版硶|66,600.00%| +|X|鍙敤浜庢暣鏁扮被鍨媩鍗佸叚杩涘埗鏍煎紡|29A| -以下程序中,能让str1等于666.0的是: +浠ヤ笅绋嬪簭涓紝鑳借str1绛変簬666.0鐨勬槸锛 -## 答案 +## 绛旀 ```csharp string str1 = string.Format("{0:F1}", 666); ``` -## 选项 +## 閫夐」 ### A diff --git "a/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/AnonymousType.md" "b/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/AnonymousType.md" index 1118337ed06a7495254865eb609af0421879169c..93c6d48547c4065cfac7b38f79bf82049f10ceaa 100644 --- "a/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/AnonymousType.md" +++ "b/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/AnonymousType.md" @@ -1,14 +1,14 @@ -# C# 3.0 特性 匿名类型 +# C# 3.0 鐗规 鍖垮悕绫诲瀷 -匿名类型提供了一种方便的方法,可以将一组只读属性封装到单个对象中,而无需先显式定义类型。类型名称由编译器生成,在源代码级别不可用。每个属性的类型由编译器推断。 -您可以通过将new运算符与对象初始值设定项一起使用来创建匿名类型。 +鍖垮悕绫诲瀷鎻愪緵浜嗕竴绉嶆柟渚跨殑鏂规硶锛屽彲浠ュ皢涓缁勫彧璇诲睘鎬у皝瑁呭埌鍗曚釜瀵硅薄涓紝鑰屾棤闇鍏堟樉寮忓畾涔夌被鍨嬨傜被鍨嬪悕绉扮敱缂栬瘧鍣ㄧ敓鎴愶紝鍦ㄦ簮浠g爜绾у埆涓嶅彲鐢ㄣ傛瘡涓睘鎬х殑绫诲瀷鐢辩紪璇戝櫒鎺ㄦ柇銆 +鎮ㄥ彲浠ラ氳繃灏唍ew杩愮畻绗︿笌瀵硅薄鍒濆鍊艰瀹氶」涓璧蜂娇鐢ㄦ潵鍒涘缓鍖垮悕绫诲瀷銆 ```csharp -var user = new { name = "Gao", id = 996, height = 172.5 }; // 此时编译器会提示匿名类型, 是 new {string name, int id, double height} +var user = new { name = "Gao", id = 996, height = 172.5 }; // 姝ゆ椂缂栬瘧鍣ㄤ細鎻愮ず鍖垮悕绫诲瀷锛 鏄 new {string name, int id, double height} Console.WriteLine(string.Format("name {0}, id {1}, height {2}", user.name, user.id, user.height)); ``` -如果一个类里面的属性和字段太多,想要用LINQ语句查找,可以试试匿名类型。以下代码举个例子,假如有一个examples是example类的集合,然后输出所有的Name,如果直接查询会把example类的所有属性和字段带过来,使用匿名类型会导致查询中返回的数据量较少。 +濡傛灉涓涓被閲岄潰鐨勫睘鎬у拰瀛楁澶锛屾兂瑕佺敤LINQ璇彞鏌ユ壘锛屽彲浠ヨ瘯璇曞尶鍚嶇被鍨嬨備互涓嬩唬鐮佷妇涓緥瀛愶紝鍋囧鏈変竴涓猠xamples鏄痚xample绫荤殑闆嗗悎锛岀劧鍚庤緭鍑烘墍鏈夌殑Name锛屽鏋滅洿鎺ユ煡璇細鎶奺xample绫荤殑鎵鏈夊睘鎬у拰瀛楁甯﹁繃鏉ワ紝浣跨敤鍖垮悕绫诲瀷浼氬鑷存煡璇腑杩斿洖鐨勬暟鎹噺杈冨皯銆 ```csharp var result = from example in examples select new { example.Name }; @@ -19,15 +19,15 @@ foreach (var item in result) } ``` -在下列选项中,可以设置一个name是“csdn”的匿名类型的是: +鍦ㄤ笅鍒楅夐」涓紝鍙互璁剧疆涓涓猲ame鏄渃sdn鈥濈殑鍖垮悕绫诲瀷鐨勬槸锛 -## 答案 +## 绛旀 ```csharp var csdn = new { name = "csdn" }; ``` -## 选项 +## 閫夐」 ### A diff --git "a/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/AutoImplementedProperties.md" "b/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/AutoImplementedProperties.md" index 6baa579b3ef510e7a0afa39ae20adcf909ebc505..228a046e154cda5ac6b490c486d67a8c7074af47 100644 --- "a/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/AutoImplementedProperties.md" +++ "b/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/AutoImplementedProperties.md" @@ -1,8 +1,8 @@ -# C# 3.0 特性 自动实现属性 +# C# 3.0 鐗规 鑷姩瀹炵幇灞炴 -在 C# 3.0 及更高版本,当属性访问器中不需要任何其他逻辑时,自动实现的属性会使属性声明更加简洁。 +鍦 C# 3.0 鍙婃洿楂樼増鏈紝褰撳睘鎬ц闂櫒涓笉闇瑕佷换浣曞叾浠栭昏緫鏃讹紝鑷姩瀹炵幇鐨勫睘鎬т細浣垮睘鎬у0鏄庢洿鍔犵畝娲併 -对于字段可以用属性来封装,上面代码的name就是用Name封装,并且使用时使用Name。C# 3.0特性支持了自动实现属性的访问器,这样就可以写成Id这样,也能实现一样的功能。这里的属性将set访问器声明为私有,那就是私有的访问级别,如果访问器只声明get访问器时,除了能在构造函数中可变,在其他任何位置都不可变。 +瀵逛簬瀛楁鍙互鐢ㄥ睘鎬ф潵灏佽锛屼笂闈唬鐮佺殑name灏辨槸鐢∟ame灏佽锛屽苟涓斾娇鐢ㄦ椂浣跨敤Name銆侰# 3.0鐗规ф敮鎸佷簡鑷姩瀹炵幇灞炴х殑璁块棶鍣紝杩欐牱灏卞彲浠ュ啓鎴怚d杩欐牱锛屼篃鑳藉疄鐜颁竴鏍风殑鍔熻兘銆傝繖閲岀殑灞炴у皢set璁块棶鍣ㄥ0鏄庝负绉佹湁锛岄偅灏辨槸绉佹湁鐨勮闂骇鍒紝濡傛灉璁块棶鍣ㄥ彧澹版槑get璁块棶鍣ㄦ椂锛岄櫎浜嗚兘鍦ㄦ瀯閫犲嚱鏁颁腑鍙彉锛屽湪鍏朵粬浠讳綍浣嶇疆閮戒笉鍙彉銆 ```csharp public class Example @@ -24,15 +24,15 @@ public class Example } ``` -如上代码,在下列选项中,不可以设置属性值的是: +濡備笂浠g爜锛屽湪涓嬪垪閫夐」涓紝涓嶅彲浠ヨ缃睘鎬у肩殑鏄細 -## 答案 +## 绛旀 ```csharp Example example = new Example(){UserId = Guid.NewGuid().ToString()}; ``` -## 选项 +## 閫夐」 ### A diff --git "a/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/ExpressionTree.md" "b/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/ExpressionTree.md" index d64959c6a8ccf23ecb1cff669611f4b95ee5e2a2..1613f5d03b63fd2c5f5edc07671038ab3f164baa 100644 --- "a/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/ExpressionTree.md" +++ "b/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/ExpressionTree.md" @@ -1,19 +1,19 @@ -# C# 3.0 特性 表达式树 +# C# 3.0 鐗规 琛ㄨ揪寮忔爲 -表达式树是定义代码的数据结构。 它们基于编译器用于分析代码和生成已编译输出的相同结构。 -以下代码创建了一个表达式并且执行了,Compile方法可以编译表达式树由描述为可执行代码的 lambda 表达式,并生成一个委托,表示 lambda 表达式。 -注意这里不能使用var来声明此表达式树,因为此操作无法执行,这是由于赋值右侧是隐式类型而导致的。 +琛ㄨ揪寮忔爲鏄畾涔変唬鐮佺殑鏁版嵁缁撴瀯銆 瀹冧滑鍩轰簬缂栬瘧鍣ㄧ敤浜庡垎鏋愪唬鐮佸拰鐢熸垚宸茬紪璇戣緭鍑虹殑鐩稿悓缁撴瀯銆 +浠ヤ笅浠g爜鍒涘缓浜嗕竴涓〃杈惧紡骞朵笖鎵ц浜嗭紝Compile鏂规硶鍙互缂栬瘧琛ㄨ揪寮忔爲鐢辨弿杩颁负鍙墽琛屼唬鐮佺殑 lambda 琛ㄨ揪寮忥紝骞剁敓鎴愪竴涓鎵橈紝琛ㄧず lambda 琛ㄨ揪寮忋 +娉ㄦ剰杩欓噷涓嶈兘浣跨敤var鏉ュ0鏄庢琛ㄨ揪寮忔爲锛屽洜涓烘鎿嶄綔鏃犳硶鎵ц锛岃繖鏄敱浜庤祴鍊煎彸渚ф槸闅愬紡绫诲瀷鑰屽鑷寸殑銆 ```csharp Expression> add = () => 1 + 2; -var func = add.Compile(); // 创建一个 delegate -var answer = func(); // 调用 delegate, 得到值3 +var func = add.Compile(); // 鍒涘缓涓涓 delegate +var answer = func(); // 璋冪敤 delegate锛 寰楀埌鍊3 Console.WriteLine(answer); ``` -根据上面例子,下列选项中,可以生成一个1+2的表达式的是: +鏍规嵁涓婇潰渚嬪瓙锛屼笅鍒楅夐」涓紝鍙互鐢熸垚涓涓1+2鐨勮〃杈惧紡鐨勬槸锛 -## 答案 +## 绛旀 ```csharp var one = Expression.Constant(1, typeof(int)); @@ -21,7 +21,7 @@ var two = Expression.Constant(2, typeof(int)); var addition = Expression.Add(one, two); ``` -## 选项 +## 閫夐」 ### A diff --git "a/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/ExtensionMethod.md" "b/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/ExtensionMethod.md" index 0b3687a58bdc4debe8500a9a7281ce86fd8692b9..f62891920c6385f5fc9c6da88df1e7be5c230acb 100644 --- "a/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/ExtensionMethod.md" +++ "b/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/ExtensionMethod.md" @@ -1,11 +1,11 @@ -# C# 3.0 特性 扩展方法 +# C# 3.0 鐗规 鎵╁睍鏂规硶 -扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。 -扩展方法是一种静态方法,但可以像扩展类型上的实例方法一样进行调用。调用扩展方法与调用在类型中定义的方法没有明显区别。 +鎵╁睍鏂规硶浣夸綘鑳藉鍚戠幇鏈夌被鍨嬧滄坊鍔犫濇柟娉曪紝鑰屾棤闇鍒涘缓鏂扮殑娲剧敓绫诲瀷銆侀噸鏂扮紪璇戞垨浠ュ叾浠栨柟寮忎慨鏀瑰師濮嬬被鍨嬨 +鎵╁睍鏂规硶鏄竴绉嶉潤鎬佹柟娉曪紝浣嗗彲浠ュ儚鎵╁睍绫诲瀷涓婄殑瀹炰緥鏂规硶涓鏍疯繘琛岃皟鐢ㄣ傝皟鐢ㄦ墿灞曟柟娉曚笌璋冪敤鍦ㄧ被鍨嬩腑瀹氫箟鐨勬柟娉曟病鏈夋槑鏄惧尯鍒 -在下列选项中,是扩展方法并实现了判断字符串中是否包含Q或q的代码的是: +鍦ㄤ笅鍒楅夐」涓紝鏄墿灞曟柟娉曞苟瀹炵幇浜嗗垽鏂瓧绗︿覆涓槸鍚﹀寘鍚玅鎴杚鐨勪唬鐮佺殑鏄細 -## 答案 +## 绛旀 ```csharp public static class Extensions @@ -25,7 +25,7 @@ public static class Extensions } ``` -## 选项 +## 閫夐」 ### A diff --git "a/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/LambdaExpression.md" "b/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/LambdaExpression.md" index ea0129e35e7b9a84013ac4ff4df32506aa13e5de..0507ad92a6cc0979245f2860452b3c0a56c1e74a 100644 --- "a/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/LambdaExpression.md" +++ "b/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/LambdaExpression.md" @@ -1,24 +1,24 @@ -# C# 3.0 特性 Lambda 表达式 +# C# 3.0 鐗规 Lambda 琛ㄨ揪寮 -Lambda表达式可采用表达式为其主体,也可以采用语句块作为其主体: +Lambda琛ㄨ揪寮忓彲閲囩敤琛ㄨ揪寮忎负鍏朵富浣擄紝涔熷彲浠ラ噰鐢ㄨ鍙ュ潡浣滀负鍏朵富浣擄細 ```csharp (input-parameters) => expression (input-parameters) => { } ``` -Lambda表达式可以没有参数,如果有参数需要在左侧添加,任何 Lambda 表达式都可以转换为委托类型。 +Lambda琛ㄨ揪寮忓彲浠ユ病鏈夊弬鏁帮紝濡傛灉鏈夊弬鏁伴渶瑕佸湪宸︿晶娣诲姞锛屼换浣 Lambda 琛ㄨ揪寮忛兘鍙互杞崲涓哄鎵樼被鍨嬨 -在下列选项中,没有编译错误并且可以输出5的平方的是: +鍦ㄤ笅鍒楅夐」涓紝娌℃湁缂栬瘧閿欒骞朵笖鍙互杈撳嚭5鐨勫钩鏂圭殑鏄細 -## 答案 +## 绛旀 ```csharp Func square = x => x * x; Console.WriteLine(square(5)); ``` -## 选项 +## 閫夐」 ### A diff --git "a/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/QueryExpression.md" "b/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/QueryExpression.md" index 538426a2160c9c876ac944de62d1c23dbc251fc5..224fc59e6e968c2d5e0c612fa8bb37747222b916 100644 --- "a/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/QueryExpression.md" +++ "b/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/QueryExpression.md" @@ -1,18 +1,18 @@ -# C# 3.0 特性 查询表达式 +# C# 3.0 鐗规 鏌ヨ琛ㄨ揪寮 -查询表达式必须以from子句开头。 它指定数据源以及范围变量。查询表达式以select或group结尾。 +鏌ヨ琛ㄨ揪寮忓繀椤讳互from瀛愬彞寮澶淬 瀹冩寚瀹氭暟鎹簮浠ュ強鑼冨洿鍙橀噺銆傛煡璇㈣〃杈惧紡浠elect鎴杇roup缁撳熬銆 -* 使用 where 子句可基于一个或多个谓词表达式,从源数据中筛选出元素。 -* 使用 select 子句可生成所有其他类型的序列。 -* 使用 group 子句可生成按指定键组织的组的序列。 -* 使用 into 关键字可以在 select 或 group 子句中创建存储查询的临时标识符。 -* 使用 orderby 子句可按升序或降序对结果进行排序。 -* 使用 join 子句可基于每个元素中指定的键之间的相等比较,将一个数据源中的元素与另一个数据源中的元素进行关联和/或合并。 -* 使用 let 子句可将表达式(如方法调用)的结果存储在新范围变量中。 +* 浣跨敤 where 瀛愬彞鍙熀浜庝竴涓垨澶氫釜璋撹瘝琛ㄨ揪寮忥紝浠庢簮鏁版嵁涓瓫閫夊嚭鍏冪礌銆 +* 浣跨敤 select 瀛愬彞鍙敓鎴愭墍鏈夊叾浠栫被鍨嬬殑搴忓垪銆 +* 浣跨敤 group 瀛愬彞鍙敓鎴愭寜鎸囧畾閿粍缁囩殑缁勭殑搴忓垪銆 +* 浣跨敤 into 鍏抽敭瀛楀彲浠ュ湪 select 鎴 group 瀛愬彞涓垱寤哄瓨鍌ㄦ煡璇㈢殑涓存椂鏍囪瘑绗︺ +* 浣跨敤 orderby 瀛愬彞鍙寜鍗囧簭鎴栭檷搴忓缁撴灉杩涜鎺掑簭銆 +* 浣跨敤 join 瀛愬彞鍙熀浜庢瘡涓厓绱犱腑鎸囧畾鐨勯敭涔嬮棿鐨勭浉绛夋瘮杈冿紝灏嗕竴涓暟鎹簮涓殑鍏冪礌涓庡彟涓涓暟鎹簮涓殑鍏冪礌杩涜鍏宠仈鍜/鎴栧悎骞躲 +* 浣跨敤 let 瀛愬彞鍙皢琛ㄨ揪寮忥紙濡傛柟娉曡皟鐢級鐨勭粨鏋滃瓨鍌ㄥ湪鏂拌寖鍥村彉閲忎腑銆 -在下列选项中,可以将examples集合中所有Count大于10的子项目按照Count从大到小的顺序格式化显示的是: +鍦ㄤ笅鍒楅夐」涓紝鍙互灏唀xamples闆嗗悎涓墍鏈塁ount澶т簬10鐨勫瓙椤圭洰鎸夌収Count浠庡ぇ鍒板皬鐨勯『搴忔牸寮忓寲鏄剧ず鐨勬槸锛 -## 答案 +## 绛旀 ```csharp from example in examples @@ -21,7 +21,7 @@ orderby example.Count descending select $"{example.Name}\t{example.Count}"; ``` -## 选项 +## 閫夐」 ### A diff --git "a/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/config.json" "b/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/config.json" index a021e842bf1501e1a2f666f0681bc60b0f8d52e9..4a3de9a79546e7bf40590d6f12212747583f44cb 100644 --- "a/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/config.json" +++ "b/data/1..NET\345\210\235\351\230\266/3.C#\347\211\271\346\200\247/1.C#3.0\347\211\271\346\200\247/config.json" @@ -9,7 +9,14 @@ "鎵╁睍鏂规硶" ], "children": [], - "export": [], + "export": [ + "AnonymousType.json", + "LambdaExpression.json", + "AutoImplementedProperties.json", + "ExtensionMethod.json", + "ExpressionTree.json", + "QueryExpression.json" + ], "keywords_must": [], "keywords_forbid": [] } \ No newline at end of file diff --git "a/data/2..NET\344\270\255\351\230\266/1.ASP.NET Core\345\272\224\347\224\250/4.Web API\345\272\224\347\224\250/WebAPI.md" "b/data/2..NET\344\270\255\351\230\266/1.ASP.NET Core\345\272\224\347\224\250/4.Web API\345\272\224\347\224\250/WebAPI.md" index 2645e0ef784b8d5b5ac2be9dabad032dca587371..84c4b38d709df440e7b74afc83b768b0fc7f3f3d 100644 --- "a/data/2..NET\344\270\255\351\230\266/1.ASP.NET Core\345\272\224\347\224\250/4.Web API\345\272\224\347\224\250/WebAPI.md" +++ "b/data/2..NET\344\270\255\351\230\266/1.ASP.NET Core\345\272\224\347\224\250/4.Web API\345\272\224\347\224\250/WebAPI.md" @@ -1,12 +1,12 @@ -# Web API应用 +# Web API搴旂敤 -应用程序接口(API,Application Programming Interface)是基于编程语言构建的结构,使开发人员更容易地创建复杂的功能。它们抽象了复杂的代码,并提供一些简单的接口规则直接使用。 +搴旂敤绋嬪簭鎺ュ彛锛圓PI锛孉pplication Programming Interface锛夋槸鍩轰簬缂栫▼璇█鏋勫缓鐨勭粨鏋勶紝浣垮紑鍙戜汉鍛樻洿瀹规槗鍦板垱寤哄鏉傜殑鍔熻兘銆傚畠浠娊璞′簡澶嶆潅鐨勪唬鐮侊紝骞舵彁渚涗竴浜涚畝鍗曠殑鎺ュ彛瑙勫垯鐩存帴浣跨敤銆 -当我们创建一个.net Core的Web API时,可以选择带有模板的,这样就自动生成了一个简单的API,而且调试的时候也会自动生成[swagger](https://swagger.io/ "swagger")打开网页可查看接口详细信息和测试。如下是ValueController的代码。 +褰撴垜浠垱寤轰竴涓.net Core鐨刉eb API鏃讹紝鍙互閫夋嫨甯︽湁妯℃澘鐨勶紝杩欐牱灏辫嚜鍔ㄧ敓鎴愪簡涓涓畝鍗曠殑API,鑰屼笖璋冭瘯鐨勬椂鍊欎篃浼氳嚜鍔ㄧ敓鎴怺swagger](https://swagger.io/ "swagger")鎵撳紑缃戦〉鍙煡鐪嬫帴鍙h缁嗕俊鎭拰娴嬭瘯銆傚涓嬫槸ValueController鐨勪唬鐮併 ```csharp -[Route("api/[controller]")] // 自定义特性,调用接口时可以"https://localhost/api/Values"(这里[controller]是继承ControllerBase的类名,也可以拼接很多,比如加[action]是方法名) +[Route("api/[controller]")] // 鑷畾涔夌壒鎬э紝璋冪敤鎺ュ彛鏃跺彲浠"https://localhost/api/Values"锛堣繖閲孾controller]鏄户鎵緾ontrollerBase鐨勭被鍚嶏紝涔熷彲浠ユ嫾鎺ュ緢澶氾紝姣斿鍔燵action]鏄柟娉曞悕锛 [ApiController] public class ValuesController : ControllerBase { @@ -19,7 +19,7 @@ public class ValuesController : ControllerBase } ``` -此时用GET调用接口会返回 +姝ゆ椂鐢℅ET璋冪敤鎺ュ彛浼氳繑鍥 ```json [ "value1", @@ -27,19 +27,19 @@ public class ValuesController : ControllerBase ] ``` -Web API还允许在方法中使用特性来切换请求方式和参数方式: +Web API杩樺厑璁稿湪鏂规硶涓娇鐢ㄧ壒鎬ф潵鍒囨崲璇锋眰鏂瑰紡鍜屽弬鏁版柟寮: ```csharp // GET api//5 -[HttpGet("{id}")] // 这里的{id}就是参数id +[HttpGet("{id}")] // 杩欓噷鐨剓id}灏辨槸鍙傛暟id public string Get(int id) { return (id * 2).ToString(); } // POST api/ -[HttpPost] // 这里用了POST方法 -public void Post([FromBody] string value) //FromBody特性,curl -X POST "https://localhost/api/Values" -H "accept: */*" -H "Content-Type: application/json" -d "\"string\"" +[HttpPost] // 杩欓噷鐢ㄤ簡POST鏂规硶 +public void Post([FromBody] string value) //FromBody鐗规э紝curl -X POST "https://localhost/api/Values" -H "accept: */*" -H "Content-Type: application/json" -d "\"string\"" { } @@ -102,16 +102,16 @@ public class TestController : ControllerBase } ``` -如上代码,在下列选项中,可以正确获取Test接口的是: +濡備笂浠g爜锛屽湪涓嬪垪閫夐」涓紝鍙互姝g‘鑾峰彇Test鎺ュ彛鐨勬槸锛 -## 答案 +## 绛旀 ``` curl -X GET "https://localhost:44326/api/Test/Sum?num1=6&num2=6" -H "accept: text/plain" curl -X GET "https://localhost:44326/api/Test/Copy/str" -H "accept: text/plain" ``` -## 选项 +## 閫夐」 ### A diff --git "a/data/2..NET\344\270\255\351\230\266/1.ASP.NET Core\345\272\224\347\224\250/4.Web API\345\272\224\347\224\250/config.json" "b/data/2..NET\344\270\255\351\230\266/1.ASP.NET Core\345\272\224\347\224\250/4.Web API\345\272\224\347\224\250/config.json" index cd361fd62ad18f55783dc0be3575ba84a0e4f567..291cb6652e5500ab2042a2b7819035f836028cf5 100644 --- "a/data/2..NET\344\270\255\351\230\266/1.ASP.NET Core\345\272\224\347\224\250/4.Web API\345\272\224\347\224\250/config.json" +++ "b/data/2..NET\344\270\255\351\230\266/1.ASP.NET Core\345\272\224\347\224\250/4.Web API\345\272\224\347\224\250/config.json" @@ -4,7 +4,9 @@ ".NET Web API" ], "children": [], - "export": [], + "export": [ + "WebAPI.json" + ], "keywords_must": [], "keywords_forbid": [] } \ No newline at end of file diff --git a/main.py b/main.py index d1e7e0e4cb65678325dacac2e7639386daa70937..dff6bf9efecbdd1a7bfe955260e2eafba314c2da 100644 --- a/main.py +++ b/main.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -from src.tree import TreeWalker +from skill_tree.tree import TreeWalker if __name__ == '__main__': walker = TreeWalker("data", "csharp", "csharp") diff --git a/requirement.txt b/requirement.txt index 4336eaa0112dd5e9d95373c505d38d989e2ef667..930557801e86f8323d6f219034f2ea894985e211 100644 --- a/requirement.txt +++ b/requirement.txt @@ -1 +1 @@ -uuid==1.30 \ No newline at end of file +skill-tree-parser~=0.0.5 \ No newline at end of file diff --git a/src/tree.py b/src/tree.py deleted file mode 100644 index 0c58d32b0da0e7099c2d2804fc97cdc35b240e28..0000000000000000000000000000000000000000 --- a/src/tree.py +++ /dev/null @@ -1,425 +0,0 @@ -import json -import logging -import os -import re -import subprocess -import sys -import uuid -import re - -id_set = set() -logger = logging.getLogger(__name__) -logger.setLevel(logging.INFO) -handler = logging.StreamHandler(sys.stdout) -formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') -handler.setFormatter(formatter) -logger.addHandler(handler) - - -def search_author(author_dict, username): - for key in author_dict: - names = author_dict[key] - if username in names: - return key - return username - - -def user_name(md_file, author_dict): - ret = subprocess.Popen([ - "git", "log", md_file - ], stdout=subprocess.PIPE) - lines = list(map(lambda l: l.decode(), ret.stdout.readlines())) - author_lines = [] - for line in lines: - if line.startswith('Author'): - author_lines.append(line.split(' ')[1]) - author_nick_name = author_lines[-1] - return search_author(author_dict, author_nick_name) - - -def load_json(p): - with open(p, 'r', encoding="utf-8") as f: - return json.loads(f.read()) - - -def dump_json(p, j, exist_ok=False, override=False): - if os.path.exists(p): - if exist_ok: - if not override: - return - else: - logger.error(f"{p} already exist") - sys.exit(0) - - with open(p, 'w+', encoding="utf8") as f: - f.write(json.dumps(j, indent=2, ensure_ascii=False)) - - -def ensure_config(path): - config_path = os.path.join(path, "config.json") - if not os.path.exists(config_path): - node = {"keywords": []} - dump_json(config_path, node, exist_ok=True, override=False) - return node - else: - return load_json(config_path) - - -def parse_no_name(d): - p = r'(\d+)\.(.*)' - m = re.search(p, d) - - try: - no = int(m.group(1)) - dir_name = m.group(2) - except: - sys.exit(0) - - return no, dir_name - - -def check_export(base, cfg): - flag = False - exports = [] - for export in cfg.get('export', []): - ecfg_path = os.path.join(base, export) - if os.path.exists(ecfg_path): - exports.append(export) - else: - flag = True - if flag: - cfg["export"] = exports - return flag - - -class TreeWalker: - def __init__( - self, root, - tree_name, - title=None, - log=None, - authors=None, - enable_notebook=None, - ignore_keywords=False - ): - self.ignore_keywords = ignore_keywords - self.authors = authors if authors else {} - self.enable_notebook = enable_notebook - self.name = tree_name - self.root = root - self.title = tree_name if title is None else title - self.tree = {} - self.logger = logger if log is None else log - - def walk(self): - root = self.load_root() - root_node = { - "node_id": root["node_id"], - "keywords": root["keywords"], - "children": [], - "keywords_must": root["keywords_must"], - "keywords_forbid": root["keywords_forbid"] - } - self.tree[root["tree_name"]] = root_node - self.load_levels(root_node) - self.load_chapters(self.root, root_node) - for index, level in enumerate(root_node["children"]): - level_title = list(level.keys())[0] - level_node = list(level.values())[0] - level_path = os.path.join(self.root, f"{index + 1}.{level_title}") - self.load_chapters(level_path, level_node) - for index, chapter in enumerate(level_node["children"]): - chapter_title = list(chapter.keys())[0] - chapter_node = list(chapter.values())[0] - chapter_path = os.path.join( - level_path, f"{index + 1}.{chapter_title}") - self.load_sections(chapter_path, chapter_node) - for index, section_node in enumerate(chapter_node["children"]): - section_title = list(section_node.keys())[0] - full_path = os.path.join( - chapter_path, f"{index + 1}.{section_title}") - if os.path.isdir(full_path): - self.check_section_keywords(full_path) - self.ensure_exercises(full_path) - - tree_path = os.path.join(self.root, "tree.json") - dump_json(tree_path, self.tree, exist_ok=True, override=True) - return self.tree - - def sort_dir_list(self, dirs): - result = [self.extract_node_env(dir) for dir in dirs] - result.sort(key=lambda item: item[0]) - return result - - def load_levels(self, root_node): - levels = [] - for level in os.listdir(self.root): - if not os.path.isdir(level): - continue - level_path = os.path.join(self.root, level) - num, config = self.load_level_node(level_path) - levels.append((num, config)) - - levels = self.resort_children(self.root, levels) - root_node["children"] = [item[1] for item in levels] - return root_node - - def load_level_node(self, level_path): - config = self.ensure_level_config(level_path) - num, name = self.extract_node_env(level_path) - - result = { - name: { - "node_id": config["node_id"], - "keywords": config["keywords"], - "children": [], - "keywords_must": config["keywords_must"], - "keywords_forbid": config["keywords_forbid"] - } - } - - return num, result - - def load_chapters(self, base, level_node): - chapters = [] - for name in os.listdir(base): - full_name = os.path.join(base, name) - if os.path.isdir(full_name): - num, chapter = self.load_chapter_node(full_name) - chapters.append((num, chapter)) - - chapters = self.resort_children(base, chapters) - level_node["children"] = [item[1] for item in chapters] - return level_node - - def load_sections(self, base, chapter_node): - sections = [] - for name in os.listdir(base): - full_name = os.path.join(base, name) - if os.path.isdir(full_name): - num, section = self.load_section_node(full_name) - sections.append((num, section)) - - sections = self.resort_children(base, sections) - chapter_node["children"] = [item[1] for item in sections] - return chapter_node - - def resort_children(self, base, children): - children.sort(key=lambda item: item[0]) - for index, [number, element] in enumerate(children): - title = list(element.keys())[0] - origin = os.path.join(base, f"{number}.{title}") - posted = os.path.join(base, f"{index + 1}.{title}") - if origin != posted: - self.logger.info(f"rename [{origin}] to [{posted}]") - os.rename(origin, posted) - return children - - def ensure_chapters(self): - for subdir in os.listdir(self.root): - self.ensure_level_config(subdir) - - def load_root(self): - config_path = os.path.join(self.root, "config.json") - if not os.path.exists(config_path): - config = { - "tree_name": self.name, - "keywords": [], - "node_id": self.gen_node_id(), - "keywords_must": [], - "keywords_forbid": [] - } - dump_json(config_path, config, exist_ok=True, override=True) - else: - config = load_json(config_path) - flag, result = self.ensure_node_id(config) - if flag: - dump_json(config_path, result, exist_ok=True, override=True) - - return config - - def ensure_level_config(self, path): - config_path = os.path.join(path, "config.json") - if not os.path.exists(config_path): - config = { - "node_id": self.gen_node_id() - } - dump_json(config_path, config, exist_ok=True, override=True) - else: - config = load_json(config_path) - flag, result = self.ensure_node_id(config) - if flag: - dump_json(config_path, config, exist_ok=True, override=True) - return config - - def ensure_chapter_config(self, path): - config_path = os.path.join(path, "config.json") - if not os.path.exists(config_path): - config = { - "node_id": self.gen_node_id(), - "keywords": [], - "keywords_must": [], - "keywords_forbid": [] - } - dump_json(config_path, config, exist_ok=True, override=True) - else: - config = load_json(config_path) - flag, result = self.ensure_node_id(config) - if flag: - dump_json(config_path, config, exist_ok=True, override=True) - return config - - def ensure_section_config(self, path): - config_path = os.path.join(path, "config.json") - if not os.path.exists(config_path): - config = { - "node_id": self.gen_node_id(), - "keywords": [], - "children": [], - "export": [] - } - dump_json(config_path, config, exist_ok=True, override=True) - else: - config = load_json(config_path) - flag, result = self.ensure_node_id(config) - if flag: - dump_json(config_path, result, exist_ok=True, override=True) - return config - - def ensure_node_id(self, config): - flag = False - if "node_id" not in config or \ - not config["node_id"].startswith(f"{self.name}-") or \ - config["node_id"] in id_set: - new_id = self.gen_node_id() - id_set.add(new_id) - config["node_id"] = new_id - flag = True - - for child in config.get("children", []): - child_node = list(child.values())[0] - f, _ = self.ensure_node_id(child_node) - flag = flag or f - - return flag, config - - def gen_node_id(self): - return f"{self.name}-{uuid.uuid4().hex}" - - def extract_node_env(self, path): - try: - _, dir = os.path.split(path) - self.logger.info(path) - number, title = dir.split(".", 1) - return int(number), title - except Exception as error: - self.logger.error(f"鐩綍 [{path}] 瑙f瀽澶辫触锛岀粨鏋勪笉鍚堟硶锛屽彲鑳芥槸缂哄皯搴忓彿") - # sys.exit(1) - raise error - - def load_chapter_node(self, full_name): - config = self.ensure_chapter_config(full_name) - num, name = self.extract_node_env(full_name) - result = { - name: { - "node_id": config["node_id"], - "keywords": config["keywords"], - "children": [], - "keywords_must": config["keywords_must"], - "keywords_forbid": config["keywords_forbid"] - } - } - return num, result - - def load_section_node(self, full_name): - config = self.ensure_section_config(full_name) - num, name = self.extract_node_env(full_name) - result = { - name: { - "node_id": config["node_id"], - "keywords": config["keywords"], - "children": config.get("children", []), - "keywords_must": config["keywords_must"], - "keywords_forbid": config["keywords_forbid"] - } - } - # if "children" in config: - # result["children"] = config["children"] - return num, result - - def ensure_exercises(self, section_path): - config = self.ensure_section_config(section_path) - flag = False - for e in os.listdir(section_path): - base, ext = os.path.splitext(e) - _, source = os.path.split(e) - if ext != ".md": - continue - mfile = base + ".json" - meta_path = os.path.join(section_path, mfile) - md_file = os.path.join(section_path, e) - self.ensure_exercises_meta(meta_path, source, md_file) - export = config.get("export", []) - if mfile not in export and self.name != "algorithm": - export.append(mfile) - flag = True - config["export"] = export - - if flag: - dump_json(os.path.join(section_path, "config.json"), - config, True, True) - - for e in config.get("export", []): - full_name = os.path.join(section_path, e) - exercise = load_json(full_name) - if "exercise_id" not in exercise or exercise.get("exercise_id") in id_set: - eid = uuid.uuid4().hex - exercise["exercise_id"] = eid - dump_json(full_name, exercise, True, True) - else: - id_set.add(exercise["exercise_id"]) - - def ensure_exercises_meta(self, meta_path, source, md_file): - _, mfile = os.path.split(meta_path) - meta = None - if os.path.exists(meta_path): - with open(meta_path) as f: - content = f.read() - if content: - meta = json.loads(content) - if "exercise_id" not in meta: - meta["exercise_id"] = uuid.uuid4().hex - if "notebook_enable" not in meta: - meta["notebook_enable"] = self.default_notebook() - if "source" not in meta: - meta["source"] = source - if "author" not in meta: - meta["author"] = user_name(md_file, self.authors) - if "type" not in meta: - meta["type"] = "code_options" - - if meta is None: - meta = { - "type": "code_options", - "author": user_name(md_file, self.authors), - "source": source, - "notebook_enable": self.default_notebook(), - "exercise_id": uuid.uuid4().hex - } - dump_json(meta_path, meta, True, True) - - def default_notebook(self): - if self.enable_notebook is not None: - return self.enable_notebook - if self.name in ["python", "java", "c"]: - return True - else: - return False - - def check_section_keywords(self, full_path): - if self.ignore_keywords: - return - config = self.ensure_section_config(full_path) - if not config.get("keywords", []): - self.logger.error(f"鑺傜偣 [{full_path}] 鐨勫叧閿瓧涓虹┖锛岃淇敼閰嶇疆鏂囦欢鍐欏叆鍏抽敭瀛") - sys.exit(1)