首页 文章 精选 留言 我的

精选列表

搜索[零点击],共10000篇文章
优秀的个人博客,低调大师

《从零开始学Swift》学习笔记(Day 44)——重写属性

重写实例属性 我们可以在子类中重写从父类继承来的属性,属性有实例属性和静态属性之分,他们在具体实现也是不同的。 实例属性的重写一方面可以重写getter和setter访问器,另一方面可以重写属性观察者。 计算静态属性需要使用getter和setter访问器,而存储属性不需要。子类在继承父类后,也可以通过getter和setter访问器重写父类的存储属性和计算属性。 下面看一个示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 class Person{ varname:String //存储属性 varage:Int //存储属性 funcdescription()->String{ return "\(name)年龄是:\(age)" } init(name:String,age:Int){ self.name=name self.age=age } } class Student:Person{ varschool:String overridevarage:Int{ //重写属性前面要添加override关键字 get{ return super .age } set{ super .age=newValue< 8 ? 8 :newValue } } convenienceinit(){ self.init(name: "Tony" ,age: 18 ,school: "清华大学" ) } init(name:String,age:Int,school:String){ self.school=school super .init(name:name,age:age) } } letstudent1=Student() print( "学生年龄:\(student1.age)" ) student1.age= 6 print( "学生年龄:\(student1.age)" ) 从属性重写可见,子类本身并不存储数据,数据是存储在父类的存储属性中的。 以上示例是重写属性getter和setter访问器,我们还可以重写属性观察者,代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 class Person{ varname:String varage:Int funcdescription()->String{ return "\(name)年龄是:\(age)" } init(name:String,age:Int){ self.name=name self.age=age } } class Student:Person{ varschool:String overridevarage:Int{ //重写了age属性观察者 willSet{ //如果只关注修改之前的调用,可以只重写willSet观察者 print( "学生年龄新值:\(newValue)" ) } didSet{ //如果只关注修改之后的调用,可以只重写didSet观察者 print( "学生年龄旧值:\(oldValue)" ) } } convenienceinit(){ self.init(name: "Tony" ,age: 18 ,school: "清华大学" ) } init(name:String,age:Int,school:String){ self.school=school super .init(name:name,age:age) } } letstudent1=Student() print( "学生年龄:\(student1.age)" ) Student1.age= 6 print( "学生年龄:\(student1.age)" ) 代码Student1.age = 6修改了age属性,修改前后的输出结果如下: 学生年龄新值:6 学生年龄旧值:18 重写静态属性 在类中静态属性定义使用class或static关键字,但是使用哪一个要看子类中是否重写该属性。class修饰的属性可以被重写,static关键字就不能被重写。 示例代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Account{ varamount:Double= 0.0 //账户金额 varowner:String= "" //账户名 varinterestRate:Double= 0.0668 //利率 //class不能换成static class varstaticProp:Double{ //静态属性staticProp return 0.0668 *1_000_000 } varinstanceProp:Double{ return self.interestRate*self.amount } } class TermAccount:Account{ //class换成static override class varstaticProp:Double{ //重写静态属性staticProp return 0.0700 *1_000_000 } } //访问静态属性 print(Account.staticProp) print(TermAccount.staticProp) 由于要被重写所以代码class var staticProp: Double中的class不能换成static。代码overrideclass var staticProp: Double中的静态属性staticProp可以使用class或static,除非在TermAccount的子类中重写属性staticProp。 本文转自 tony关东升 51CTO博客,原文链接:http://blog.51cto.com/tonyguan/1747501,如需转载请自行联系原作者

优秀的个人博客,低调大师

《从零开始学Swift》学习笔记(Day 59)——代码排版

代码排版包括:空行、空格、断行和缩进等内容。代码排版内容比较多工作量很多,但是非常重要。 空行 空行将逻辑相关的代码段分隔开,以提高可读性。下列情况应该总是添加空行: 类型声明之前。 import语句前后。 两个方法或函数之间。 块注释或单行注释之前。 方法或函数内的两个逻辑段之间,用以提高可读性。 一个源文件的两个片段之间。 空格 在代码中有些位置是需要有空格的,这个工作量也是很大的。下列是使用空格的规范: 1.赋值符号“=”前后有一个空格。var或let与标识符之间有一个空格。所有的二元运算符,应该使用空格将之与操作数分开。一元操作符和操作数之间不因该加空格,如:++、--等。示例如下。 1 2 3 vara= 10 varc= 10 a+=c+d 2.小左括号“(”之后,小右括号“)”之前不要有空格。示例如下。 1 a=(a+b)/(c*d) 3.大左括号“{”之前有一个空格。示例如下。 1 2 3 while a==d{ n++ } 4.在方法或函数参数之前间有一个空格,参数冒号与数据类型之间有一个空格。 推荐使用: 1 2 3 4 functableView(tableView:UITableView,didSelectRowAtIndexPathindexPath:NSIndexPath){ ... } 不推荐使用: 1 2 3 functableView(tableView:UITableView,didSelectRowAtIndexPathindexPath:NSIndexPath){ ... } 断行 一行代码的长度尽量避免超过80个字符,为了便于查看是否一行代码超出80个字符,很多IDE开发工具都可以在编辑窗口设置显示80行竖线。在Xcode中设置过程是打开菜单Xcode→Preferences,选择Text Editing标签,选中Show→Page guideat column。 由于有的代码比较长需要断行,可以依据如下一般规范断开: 在一个逗号后面断开。 在一个操作符前面断开,要选择较高级别运算符断开,而非较低级别运算符断开。 新的一行应该与上一行缩进两个级别(8个空格) 缩进 4个空格常被作为缩进排版的一个单位,在开发时候使用制表符进行缩进,虽然默认情况下一个制表符等于8个空格,但是在不同的IDE工具中可能设置的一个制表符与空格对应个数会有所不同。在Xcode中默认是一个制表符对应4个空格,我们可以在Xcode中打开菜单Xcode→Preferences,选择Text Editing→Indentation标签,可以在Tab width中进行设置。 缩进可以依据如下一般规范: 在函数、方法、闭包、控制语句、计算属性等包含大括号“{}”代码块中,代码块中的内容与首行缩进一个级(4个空格)。 如果是if语句中条件表达式的断行,那么新的一行应该与上一行缩进两个级别(8个空格),再往后的断行要与第一次的断行对齐。 本文转自 tony关东升 51CTO博客,原文链接:http://blog.51cto.com/tonyguan/1748346,如需转载请自行联系原作者

优秀的个人博客,低调大师

《从零开始学Swift》学习笔记(Day 27)——可选类型

可选类型: 我们先看看如下代码: 1 2 3 4 varn1:Int= 10 n1=nil //编译错误 letstr:String=nil //编译错误 Int和String类型不能接受nil的,但程序运行过程中有时被复制给nil是在所难免的,Swift为每一种数据类型提供一种可选类型(optional),即在某个数据类型后面加上问号(?)或感叹号(!),修改前文示例代码: 1 2 3 4 varn1:Int?= 10 n1=nil letstr:String!=nil Int?和String!都是原有类型Int和String可选类型,它们可以接受nil。 可选类型值拆包 在可选类型的问号(?)或感叹号(!)究竟有什么区别呢?这与可选类型的“拆包”(unwrapping)有关,拆包是将可选类型变成普通类型,如果我们直接打印非空的可选类型值,代码如下: 1 2 varn1:Int?= 10 print(n1) 输出的结果是Optional(10),而非10。所以试图计算表达式n1+ 100会发生编译错误,代码如下: 1 2 varn1:Int?= 10 print(n1+ 100 ) //发生编译错误 需要对可选类型值进行“拆包”是必要地。 “拆包”分为显示拆包和隐性拆包。 使用问号(?)声明的可选类型,在拆包时需要使用感叹号(!),这种拆包方式称为“显式拆包”; 使用感叹号(!)声明的可选类型,在拆包时可以不使用感叹号(!),这种表示方式称为“隐式拆包”。 看看下面代码: 1 2 3 4 5 varn1:Int?= 10 print(n1!+ 100 ) //显式拆包 varn2:Int!= 100 print(n2+ 200 ) //隐式拆包 本文转自 tony关东升 51CTO博客,原文链接:http://blog.51cto.com/tonyguan/1746587,如需转载请自行联系原作者

优秀的个人博客,低调大师

《从零开始学Swift》学习笔记(Day 26)——可选链

在Swift程序表达式中会看到问号(?)和感叹号(!),它们代表什么含义呢?这些符号都与可选类型和可选链相关,下面来看看可选链。 可选链: 类图: 它们之间是典型的关联关系类图。这些类一般都是实体类,实体类是系统中的人、事、物。Employee通过dept属性与Department关联,Department通过comp属性与Company关联。 下面看示例代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Employee{ varno:Int= 0 varname:String= "Tony" varjob:String? varsalary:Double= 0 vardept:Department=Department() } class Department{ varno:Int= 10 varname:String= "SALES" varcomp:Company=Company() } class Company{ varno:Int= 1000 varname:String= "EOrient" } letemp=Employee() //Employee实例 print(emp.dept.comp.name) // emp.dept.comp.name可以引用到Company实例,形成一个引用的链条,但是这个“链条”任何一个环节“断裂”都无法引用到最后的目标(Company实例)。 给定一个Employee实例,一定会有一个Department与其关联。但现实是一个新入职员工未必有部门,这种关联关系有可能有值,也有可能没有值,我们需要使用可选类型(Department?)声明dept属性。 修改代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Employee{ varno:Int= 0 varname:String= "Tony" varjob:String? varsalary:Double= 0 vardept:Department? //=Department() } class Department{ varno:Int= 10 varname:String= "SALES" varcomp:Company? //=Company() } class Company{ varno:Int= 1000 varname:String= "EOrient" } letemp=Employee() print(emp.dept!.comp!.name) //显示拆包 print(emp.dept?.comp?.name) //可选链 其中可选类型的引用,可以使用感叹号(!)进行显示拆包,代码修改如下: 1 print(emp.dept!.comp!.name) 但是显示拆包有一个弊端,如果可选链中某个环节为nil,将会导致代码运行时错误。我们可以采用更加“温柔”的引用方式,使用问号(?)来代替原来感叹号(!)的位置,如下所示: 1 print(emp.dept?.comp?.name) 本文转自 tony关东升 51CTO博客,原文链接:http://blog.51cto.com/tonyguan/1746584,如需转载请自行联系原作者

优秀的个人博客,低调大师

《从零开始学Swift》学习笔记(Day 16)——字典集合

Swift字典表示一种非常复杂的集合,允许按照某个键来访问元素。字典是由两部分集合构成的,一个是键(key)集合,一个是值(value)集合。键集合是不能有重复元素的,而值集合是可以重复的,键和值是成对出现的。 字典声明与初始化 Swift字典类型是Dictionary,也是一个泛型集合。 在声明一个Dictionary类型的时候可以使用下面的语句之一。 1 2 varstudentDictionary1:Dictionary<Int,String> varstudentDictionary2:[Int:String] 声明的字典需要进行初始化才能使用,字典类型往往是在声明的同时进行初始化的。示例代码如下: 1 2 3 4 5 varstudentDictionary1:Dictionary<Int,String> =[ 102 : "张三" , 105 : "李四" , 109 : "王五" ] varstudentDictionary2=[ 102 : "张三" , 105 : "李四" , 109 : "王五" ] letstudentDictionary3=[ 102 : "张三" , 105 : "李四" , 109 : "王五" ] 字典遍历 字典遍历过程可以只遍历值的集合,也可以只遍历键的集合,也可以同时遍历。这些遍历过程都是通过for-in循环实现的。 下面是遍历字典的示例代码: 1

优秀的个人博客,低调大师

《从零开始学Swift》学习笔记(Day 31)——存储属性

Swift中的属性分为存储属性和计算属性,存储属性就是Objective-C中的数据成员,计算属性不存储数据,但可以通过计算其他属性返回数据。 存储属性可以存储数据,分为常量属性(用关键字let定义)和变量属性(用关键字var定义)。 存储属性概念: 我们在前面曾用到过属性,Employee类和Department结构体。它们的类图如下,Employee的部门属性dept与Department之间进行了关联。 我们可以在定义存储属性时指定默认值,示例代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Employee{ letno:Int= 0 varname:String= "" varjob:String? varsalary:Double= 0 vardept:Department? } structDepartment{ letno:Int= 0 varname:String= "" } letemp=Employee() emp.no= 100 //编译错误:修改常量属性,程序会发生编译错误 letdept=Department() dept.name= "SALES" //编译错误:dept是值类型,值类型不能修改,即便它的属性name是变量属性,也不能修改 letemp1=Employee() emp1.name= "Tony" 本文转自 tony关东升 51CTO博客,原文链接:http://blog.51cto.com/tonyguan/1746594,如需转载请自行联系原作者

优秀的个人博客,低调大师

《从零开始学Swift》学习笔记(Day 49)——扩展声明

声明扩展的语法格式如下: 1 2 3 extension类型名{ //添加新功能 } 声明扩展的关键字是extension,“类型名”是Swift中已有的类型,包括类、结构体和枚举,但是我们仍然可以扩展整型、浮点型、布尔型、字符串等基本数据类型,这是因为这些类型本质上也是结构体类型。打开Int的定义如下: 1 2 3 4 5 6 7 8 9 structInt:SignedInteger{ init() init(_value:Int) static funcconvertFromIntegerLiteral(value:Int)->Int typealiasArrayBoundType=Int funcgetArrayBoundValue()->Int static varmax:Int{get} static varmin:Int{get} } 从定义可见Int是结构体类型。不仅是Int类型,我们熟悉的整型、浮点型、布尔型、字符串等数据类型本质上都是结构体类型。 Swift中的扩展机制可以在原始类型中添加的新功能包括: 实例计算属性和类型计算属性 实例方法和类型方法 构造函数 下标 还有嵌套类型等内容也可以扩展,扩展还可以遵从协议。 本文转自 tony关东升 51CTO博客,原文链接:http://blog.51cto.com/tonyguan/1747536,如需转载请自行联系原作者

优秀的个人博客,低调大师

《从零开始学Swift》学习笔记(Day 45)——重写方法

重写实例方法 在子类中重写从父类继承来的实例方法和静态方法。先介绍实例方法的重写。 下面看一个示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 class Person{ varname:String varage:Int funcdescription()->String{ //实例方法 return "\(name)年龄是:\(age)" } class funcprintClass()->(){ //静态方法 print( "Person打印..." ) } init(name:String,age:Int){ self.name=name self.age=age } } class Student:Person{ varschool:String convenienceinit(){ self.init(name: "Tony" ,age: 18 ,school: "清华大学" ) } init(name:String,age:Int,school:String){ self.school=school super .init(name:name,age:age) } overridefuncdescription()->String{ //重写实例方法description,重写的方法前面要添加关键字override print( "父类打印\(super.description())" ) return "\(name)年龄是:\(age),所在学校:\(school)。" } override class funcprintClass()->(){ //重写静态方法printClass print( "Student打印..." ) } } letstudent1=student() print( "学生1:\(student1.description())" ) //调用了description方法 Person.printClass() Student.printClass() 使用super.description()语句调用父类的description方法,其中super指代父类实例。 重写静态方法printClass,在静态方法中不能访问实例属性。 调用了description方法。由于在子类中重写了该方法,所以调用的是子类中的description方法。输出结果是: 父类打印Tony年龄是: 18 学生1:Tony年龄是: 18,所在学校:清华大学。 为了测试静态方法重写,调用Person.printClass()语言,它是调用父类的printClass静态方法,输出结果是: Person打印... 调用Student.printClass()语言,它是调用子类的printClass静态方法,输出结果是: Student打印... 重写静态方法 与类的静态属性定义类似,静态方法使用class或static关键字,但是使用哪一个要看子类中是否重写该方法。class修饰的静态方法可以被重写,static关键字就不能被重写。 示例代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Account{ varowner:String= "Tony" //账户名 //不能换成static class funcinterestBy(amount:Double)->Double{ //静态方法 return 0.08886 *amount } } class TermAccount:Account{ //定期账户 //可以换成static override class funcinterestBy(amount:Double)->Double{ //静态方法 return 0.09 *amount } } //调用静态方法 print(Account.interestBy(10_000. 00 )) print(TermAccount.interestBy(10_000. 00 )) 由于被重写所以代码class funcinterestBy(amount: Double) -> Double中的class不能换成static。静态方法interestBy可以使用class或static,除非在TermAccount的子类中重写方法interestBy。 本文转自 tony关东升 51CTO博客,原文链接:http://blog.51cto.com/tonyguan/1747504,如需转载请自行联系原作者

优秀的个人博客,低调大师

《从零开始学Swift》学习笔记(Day 46)——下标重写

下标是一种特殊属性。子类属性重写是重写属性的getter和setter访问器,对下标的重写也是重写下标的getter和setter访问器。 下面看一个示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 classDoubleDimensionalArray{ letrows:Int,columns:Int vargrid:[Int] init(rows:Int,columns:Int){ self.rows=rows self.columns=columns grid=Array(count:rows*columns,repeatedValue: 0 ) } subscript(row:Int,col:Int)->Int{ //定义下标 get{ return grid[(row*columns)+col] } set{ grid[(row*columns)+col]=newValue } } //定义下标 } class SquareMatrix:DoubleDimensionalArray{ overridesubscript(row:Int,col:Int)->Int{ //重写父类下标 get{ return super .grid[(row*columns)+col] } set{ super .grid[(row*columns)+col]=newValue*newValue } } } varary2=SquareMatrix(rows: 5 ,columns: 5 ) for vari= 0 ;i< 5 ;i++{ for varj= 0 ;j< 5 ;j++{ ary2[i,j]=i+j } } for vari= 0 ;i< 5 ;i++{ for varj= 0 ;j< 5 ;j++{ print( "\t\t\(ary2[i,j])" ) } print( "\n" ) } 其中super.grid[(row * columns) + col]语句中使用super调用父类的grid属性。 其中super.grid[(row * columns) + col] = newValue * newValue语句是给父类的grid属性赋值。 本文转自 tony关东升 51CTO博客,原文链接:http://blog.51cto.com/tonyguan/1747531,如需转载请自行联系原作者

优秀的个人博客,低调大师

《从零开始学Swift》学习笔记(Day 36)——静态方法

静态方法与静态属性类似,Swift中定义了静态方法,也称为类型方法。静态方法的定义与静态属性类似,枚举和结构体的静态方法使用的关键字是static;类静态方法使用的关键字是class或static,如果使用static定义,则该方法不能在子类中被重写(override);如果使用class定义,则该方法可以被子类重写。 结构体静态方法 看一个结构体静态方法的示例,代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 structAccount{ varowner:String= "Tony" //声明实例属性账户名 static varinterestRate:Double= 0.0668 //声明静态属性利率 static funcinterestBy(amount:Double)->Double{ //定义静态方法 return interestRate*amount } funcmessageWith(amount:Double)->String{ //定义实例方法 letinterest=Account.interestBy(amount) return "\(self.owner)的利息是\(interest)" } } //调用静态方法 print(Account.interestBy(10_000. 00 )) varmyAccount=Account() //调用实例方法 print(myAccount.messageWith(10_000. 00 )) 枚举静态方法 看一个枚举静态方法的示例,代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 enum Account{ case 中国银行 case 中国工商银行 case 中国建设银行 case 中国农业银行 static varinterestRate:Double= 0.0668 //声明静态属性利率 static funcinterestBy(amount:Double)->Double{ //定义静态方法 return interestRate*amount } } //调用静态方法 print(Account.interestBy(10_000. 00 )) //调用静态方法 从示例可以看出,结构体和枚举的静态方法使用定义没有区别。 类静态方法 看一个类静态方法的示例,代码如下: 1 2 3 4 5 6 7 8 9 10 11 class Account{ varowner:String= "Tony" //账户名 //可以换成static class funcinterestBy(amount:Double)->Double{ //使用关键字class定义静态方法 return 0.08886 *amount } } //调用静态方法 print(Account.interestBy(10_000. 00 )) //调用静态方法 本文转自 tony关东升 51CTO博客,原文链接:http://blog.51cto.com/tonyguan/1746990,如需转载请自行联系原作者

优秀的个人博客,低调大师

从零开始玩人工智能-人脸 API-03

前文我们尝试写了一个完整的人脸验证过程,从创建一个组,一个人,到为人提供照片,并训练AI,直至最后提供一张照片让 AI 利用 Face API 判断是不是这个特定的人。 另一个经常会用到的人脸识别,是在一张照片中查找认识的人。Facebook什么的挺早就能够识别照片中的人并可以让你给他们打上标签。其实,利用Face API做类似的事情也一点不复杂。不信我们用代码来看看。 为了说明在一张合影中 AI 能够找到并识别特定人,我用了去年峰会中国MVP及MVP Lead梁迪和微软CEO萨蒂亚·纳德拉(Satya Nadella)、微软全球资深副总裁沈向洋、微软全球资深副总裁潘正磊的合影来做代码范例,也算是扯虎皮做大旗吧哈哈哈。 首先,使用前文示例代码中用到的Detect方法来识别照片中的人脸。 说实话,我有点担心。这张照片里的人好多啊,AI 能够都识别出来么? 呼啦啦返回了46个faceId,我趴在照片上一顿数,还真的是一个不落都识别出来了,厉害厉害! 在这里我遇到了一个问题。如前文介绍的,Detect方法识别出来的人脸会以JSON形式返回,而两层及两层以上的数据结构在转成Python的数据时,不再是dict,而是list。多层的数据意味着多层的list对象。上一次因为数据简单,直接使用了List的下标来定位数据。这一次就要老老实实遍历进行处理了。因此,for语句和list.append()就学会使用了。 由这个问题引发的另外一个问题是,生成的List需要提供给下一步Face的Identify方法作为输入。按照API文档的说明,输入应该形如: 在“faceIds”这里,应该输入所有经由Detect识别出的人脸的ID。所以我把上一步获得的List转换成了JSON格式然后拼装这个请求的body。结果……报错了……冷静地print出来list和body,跟文档进行比较,原来多了对’’’号…… 原来拼装这个JSON的时候,使用List对象facesId就可以了。使用json的dumps()把List转成json,我多此一举了。那为什么又报Error:0呢?仔细看文档,用于Identify方法的人脸数量,应该1到10之间。我们输入给AI的Face ID大大超过了这个数量,所以……报错了……那该怎么办呢?我可以分批处理,也可以裁剪照片。因为后续还要试试找不到人怎么办,所以我对照片进行了不同的裁剪。 返回的json格式形如: 如果没有对应到人,faceId对应的“condidates”就会显示为[],即空。而对应到人的faceId对应会有识别出的人的personId和相识度评分confidence。看来要把这个结果滤出来做点操作还是有点小复杂啊,一样,使用for语句逐个下标处理List。 使用两层List的下标读取,就能够成功拆分从Face API返回的json数据了。我记得人脸识别的Verify方法里,判断是否本人的参考值为0.5,因此在这里如果系统返回相识度评分大于0.5,我就继续从Face ID再去识别具体的人是谁。 果然,Face API从合影照片中认出了我~那么如果我不在照片里呢? Face API确实没有发现通过training认识的人~ 细心的你发现了吧,两次照片检测的Face ID怎么全部不一样?还记得前文我们说过的吗?Detect生成的Face ID是临时的,会在24小时之后清除,所以每次获得的ID都不同,即使是同一张脸。而关联到人的脸,其Face ID就是持久的,可以在需要的时候使用。 这么牛的合影,难道只识别我自己吗?当然不,我们要试试 AI 能不能识别多个人~ 立刻上网为这三位大神各自找了三张照片。找的过程中发现,潘女士原来早在2010年就参加过MVP的Open Day,难怪上次MVP Round Table的时候觉得那么熟悉,看我这糟糕的记性… 赶紧在上次创建的person group里再创建了三个person,每人传输了上图的三张照片。 再次运行代码,这一次,AI 在合影中就识别出了四个人了,厉害厉害~ 利用Azure Cognitive Services中的Face API,哪怕没有任何深入的 AI 知识,哪怕没有熟练的编程技巧,只需要简单的几十行代码,就能够实现有趣的人脸识别。 本文转自HaoHu 51CTO博客,原文链接:http://blog.51cto.com/haohu/2073059,如需转载请自行联系原作者

优秀的个人博客,低调大师

《从零开始学Swift》学习笔记(Day 29)——访问级别

访问级别: Swift提供了3种不同访问级别,对应的访问修饰符为:public、internal和private。这些访问修饰符可以修饰类、结构体、枚举等面向对象的类型,还可以修饰变量、常量、下标、元组、函数、属性等内容。 public。可以访问自己模块中的任何public实体。如果使用import语句引入其他模块,我们可以访问其他模块中的public实体。 internal。只能访问自己模块的任何internal实体,不能访问其他模块中的internal实体。internal可以省略,换句话说,默认访问限定是internal。 private。只能在当前源文件中使用的实体,称为私有实体。使用private修饰,可以用作隐藏某些功能的实现细节。 使用访问修饰符的示例代码如下: 1 2 3 4 5 6 7 public class PublicClass{} internalclassInternalClass{} private class PrivateClass{} public varintPublicVariable= 0 letintInternalConstant= 0 private funcintPrivateFunction(){} 使用最佳访问级别: 由于中Swift中访问限定符能够修饰的实体很多,使用起来比较繁琐,下面我们给出一些最佳实践。 1.统一性原则 原则1:如果一个类型(类、结构体、枚举)定义为internal或private,那么类型声明的变量或常量不能使用public访问级别。因为public的变量或常量可以被任何人访问,而internal或private的类型不可以。 原则2:函数的访问级别不能高于它的参数和返回类型(类、结构体、枚举)的访问级别。假设函数声明为public级别,而参数或者返回类型声明为internal或private,就会出现函数可以被任何人访问,而它的参数和返回类型不可以访问的矛盾情况。 2.设计原则 如果我们编写的是应用程序,应用程序包中的所有Swift文件和其中定义的实体,都是供本应用使用的,而不是提供其他模块使用,那么我们就不用设置访问级别了,即使用默认的访问级别。 如果我们开发的是框架,框架编译的文件不能独立运行,因此它天生就是给别人使用的,这种情况下我们要详细设计其中的Swift文件和实体的访问级别,让别人使用的可以设定为public,不想让别人看到的可以设定为internal或private。 3.元组类型的访问级别 元组类型的访问级别遵循元组中字段最低级的访问级别,例如下面的代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 private class Employee{ varno:Int= 0 varname:String= "" varjob:String? varsalary:Double= 0 vardept:Department? } structDepartment{ varno:Int= 0 varname:String= "" } private letemp=Employee() vardept=Department() private varstudent1=(dept,emp)① 4.枚举类型的访问级别 枚举中成员的访问级别继承自该枚举,因此我们不能为枚举中的成员指定访问级别。示例代码如下: 1 2 3 4 5 6 7 public enum WeekDays{ case Monday case Tuesday case Wednesday case Thursday case Friday } 由于WeekDays枚举类型是public访问级别,因而它的成员也是public级别。 本文转自 tony关东升 51CTO博客,原文链接:http://blog.51cto.com/tonyguan/1746589,如需转载请自行联系原作者

优秀的个人博客,低调大师

《从零开始学Swift》学习笔记(Day 32)——计算属性

计算属性本身不存储数据,而是从其他存储属性中计算得到数据。 计算属性概念: 计算属性提供了一个getter(取值访问器)来获取值,以及一个可选的setter(设置访问器)来间接设置其他属性或变量的值。计算属性的语法格式如下: 1 2 3 4 5 6 7 8 9 10 11 12 面向对象类型类型名{ 存储属性 ...... var计算属性名:属性数据类型{ get{ return 计算后属性值 } set(新属性值){ ...... } } } 定义计算属性比较麻烦,要注意后面的几个大括号的对齐关系。 我们先看一个示例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import Foundation class Employee{ varno:Int= 0 varfirstName:String= "Tony" //存储属性 varlastName:String= "Guan" //存储属性 varjob:String? varsalary:Double= 0 lazyvardept:Department=Department() varfullName:String{ //计算属性 get{ return firstName+ "." +lastName //返回拼接的结果 } set(newFullName){ //存储传递进来的参数值 varname=newFullName.componentsSeparatedByString( "." ) firstName=name[ 0 ] lastName=name[ 1 ] } } } structDepartment{ letno:Int= 0 varname:String= "" } varemp=Employee() print(emp.fullName) //取出属性值 emp.fullName= "Tom.Guan" //给属性赋值 print(emp.fullName) 只读计算属性: 计算属性可以只有getter访问器,没有setter访问器,这就是只读计算属性。指定计算属性不仅不用写setter访问器,而且get{}代码也可以省略。与上一节相比,代码将大大减少。修改上一节示例为只读计算属性,代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Employee{ varno:Int= 0 varfirstName:String= "Tony" varlastName:String= "Guan" varjob:String? varsalary:Double= 0 lazyvardept:Department=Department() varfullName:String{ //简洁的setter访问器 return firstName+ "." +lastName } } structDepartment{ letno:Int= 0 varname:String= "" } varemp=Employee() print(emp.fullName) 只读计算属性不能够赋值,下列语句是错误的。 1 emp.fullName= "Tom.Guan" 本文转自 tony关东升 51CTO博客,原文链接:http://blog.51cto.com/tonyguan/1746597,如需转载请自行联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册