Android必备之Kotlin入门(1):基础知识
wptr33 2024-12-03 18:45 19 浏览
1:摘要
Kotlin是JetBrains公司开发与设计的一款编程语言,其第一个版本在2011年被公布,并在2012年被开源,2017年Google宣布kotlin正式成为Android开发的第一语言。事实上,熟练地使用kotlin可以大大提高开发效率。关于Kotlin的知识,我将会用两篇文章来介绍,第一篇介绍Kotlin相关的基础知识,第二篇文章介绍Kotlin的一些高级特性,我将尽可能用简单易懂的表达方式向大家介绍相关知识点,欢迎大家关注。
2:为什么可以使用kotlin开发Android应用?
我们知道Android是Google家的产品,那么JetBrains作为一家第三方公司,其开发的kotlin为什么有支持Android的能力?
想要回答这个问题,我们需要从程序的运行的机制来分析。
编程语言分为两大类:
- 编译型语言:编译器先将代码编译为计算机可以识别的二进制文件,然后直接执行二进制文件
- 解释型语言:解释器在程序运行时实时读取代码并将其解释成计算机可以理解的二进制数据进而执行
那么Android原本的开发语言Java属于哪类语言呢?有的同学可能会说因为Java是先编译(javac命令)后运行的,所以Java是编译型语言,而有的熟悉JVM的同学又会说因为JVM中有解释器的存在,所以是解释型语言。正确答案是后者,那么如何解释前者中Java的编译过程呢?不错,Java代码在执行之前确实需要编译,这也是为什么会有javac命令存在的原因,但是其编译的产物并不是计算机可以直接识别的二进制文件,而是一种特殊的class文件,在运行时Java虚拟机(Android中的ART)会对class文件进行实时识别,然后实时执行,所以Java属于解释型语言。
我们再来回到最初的问题:kotlin为什么有支持Android的能力?
答案很简单,既然Android可以识别Java编译的class文件从而运行java程序,那么只要kotlin保证自己编译的产物也是和Java一样的class文件即可,事实上kotlin也是这么做的,也就是说,对Android的ART来说,kotlin和java并没有任何区别,因为其只关心class文件是什么,至于class文件是由哪一门程序语言编译产生的并不关心,这也就解释了为什么可以使用kotlin开发Android应用程序。
了解了kotlin的大致原理后,我们就来具体学习kotlin这门语言,首先从最基础的变量和函数学起。
3:变量和函数
3.1:变量
kotlin中的声明变量有两个关键字:
- val,value的缩写,表示“不可变”变量,该类型的变量在被赋值后不能再改变,相当于Java中给变量加上了final关键字
- var,variable的缩写,表示“可变”变量,该类型的变量在被赋值后可以继续被赋予新值
比如:
fun main(){
val x=10
var y=20
x=20
y=30
}
编译器会报错:
提示val类型的变量不可被重新赋值。
大家可能会发现,我上面写的代码没有声明x和y的类型,但是程序照样可以正常运行,这是因为kotlin有强大的类型推导机制,也就是说,因为它看到你给x赋值10,而10是一个整型,所以它认为x就是一个整型,所以:
val x=10
相当于Java中的:
final int x=10
那如果我想指定某个变量的值呢?语法是:
val x:Int=10
即使用 :来指定遍历的类型,同时也可以看到,kotlin中的整型值Int而不是java中的int,因为kotlin完全摒弃了Java中的基本数据类型,所有的数据类型都是对象,具体Java与Kotlin数据类型关系如下表所示:
可能有的读者会有疑问,既然kotlin中有val和var两种类型的变量,那在实际编程中如何判断一个变量应该用val修饰还是var修饰?首先我们应该明确,越不可变的变量其稳定性越高,因为你可以很明确地知道它的值,它不会被其他人改变,如果出现问题,你可以首先排除是它的问题,所以,好的编程习惯是尽量保证变量不可变,即对一个新变量的声明,如果可以用val,尽量用val,除非val不能满足你的实际需求,再用var,这样可以保证你的程序尽可能地健壮。
3.2:函数
函数是运行代码的载体,一个函数中可以写多行代码、实现复杂的逻辑,函数运行时会依次运行函数的代码,kotlin中函数的声明方法如下:
可以看到,一个函数主要由5部分构成:
- fun,是定义函数的关键字
- 函数名
- 参数,格式为 参数名:参数类型
- 返回值类型,表示该函数的返回值类型
- 函数体,该函数具体的逻辑
另外,在kotlin中还有一个语法糖,在日常开发中会经常用到:当一个函数的函数体中只有一行代码时,可以不必编写函数体,可以直接用等号函数定义和这一行代码连接起来即可,比如:
fun functionName(param1: Int, param2: String): Int = 0
4:程序的控制逻辑
程序的执行语句主要有三种:顺序语句、条件语句、循环语句。顺序语句很简单,按照想要的顺序一行一行写代码即可,这里主要介绍条件语句和循环语句。
4.1:条件语句
kotlin中条件语句主要有两种实现方式:if和when。
4.1.1:if
比如我们要写一个找出两个数中较大的数并将其返回的函数,使用kotlin的if语句可以这样写:
fun getTheLargerOne(num1: Int, num2: Int): Int {
var largerOne=0
if (num1 > num2) {
largerOne=num1
} else {
largerOne=num2
}
return largerOne
}
逻辑很好理解,不做过多赘述,从这个函数看,kotlin中的if和Java中的if没什么区别,但是事实上kotlin中的if相比于java中的if多了一个“具有返回值”的特性,即kotlin中的if会返回if语句中最后一行代码的返回值。所以,上述代码可以简化为:
fun getTheLargerOne(num1: Int, num2: Int): Int {
var largerOne=if (num1 > num2) {
num1
} else {
num2
}
return largerOne
}
进一步简化,我们可以去掉largerOne这个变量的引入:
fun getTheLargerOne(num1: Int, num2: Int): Int {
return if (num1 > num2) {
num1
} else {
num2
}
}
这时代码已经很简洁了,但是想想我们在介绍函数的时候,介绍过一个语法糖:当一个函数的函数体中只有一行代码时,可以不必编写函数体,可以直接用等号函数定义和这一行代码连接起来即可。所以,我们可以继续将程序简化为:
fun getTheLargerOne(num1: Int, num2: Int) = if (num1 > num2) num1 else num2
怎么样,现在的程序是不是比简化之前的版本更加简洁。
4.1.2:when
when语句类似Java中的switch,但是比switch更加强大。Java中的switch只能传入整型或短于整型的变量作为条件(JDK1.7之后增加了对字符串变量的支持),所以适用范围很窄,另外switch的每一个case最后都要手动加上break,否则会继续执行下一个case,这个特性既繁琐又极易引出bug。kotlin中的when完美解决了上述switch的痛点,而且还增加了很多新特性。我们来以一个例子说明when的用法,输入一个学生的姓名,输出他的成绩,用if来写的话应该是这样:
fun getScore(name: String) = if (name == "张三") 70 else if (name == "李四") 80 else if (name == "小明") 90 else 60
可以看到,当判断条件比较多的时候使用if就显得代码很繁琐,这时候就可以使用when来优化:
fun getScore(name: String) = when (name) {
"张三" -> 70
"李四" -> 80
"小明" -> 90
else -> 60
}
可以看到,使用when优化之后的代码简洁了很多,另外,从代码你应该也看出来了,when和if一样,可以有返回值,返回值也是执行的最后一行代码。when语句允许传入一个任意类型的参数,然后可以在when的结构体中定义一系列的条件,格式为:
匹配值->{逻辑}
当逻辑只有一行的时候可以省略{},上面的例子就是省略{}的结果。另外,when还有一种不带参数的用法,比如我们想要实现所有姓薛的人分数都是100分,使用带参数的when可能需要:
fun getScore(name: String) = when (name) {
"薛之谦" -> 100
"学狗蛋" -> 100
"薛爱国" -> 100
"张三" -> 70
"李四" -> 80
"小明" -> 90
else -> 60
}
我们可以使用不带参数的when来实现相同的逻辑:
fun getScore(name: String) = when {
name.startsWith("薛") -> 100
name == "张三" -> 70
name == "李四" -> 80
name == "小明" -> 90
else -> 60
}
4.2:循环语句
kotlin中提供了两种循环,一种是while,另一种是for,while的用法和特性与java一样,所以不做过多介绍,这里主要介绍一下kotlin中for循环的用法。kotlin中的for循环主要是for-in,在介绍for-in之前我们先来介绍一下区间的概念。kotlin中区间的声明格式如下:
val range=1..10
这时range=[1,2,3,4,5,6,7,8,9,10],即kotlin使用..来创建一个区间,且区间的两端都是闭区间的。那如果想创建一个开区间的区间呢?kotlin给我们提供了until关键字:
val range=1 until 10
这时range=[1,2,3,4,5,6,7,8,9],即until代表的区间为”左闭右开“。现在我们可以用for来遍历区间:
for(i in 1..10){
println(i)
}
或者:
for (i in 1 until 10){
println(i)
}
那么如果想要每次遍历时i加2怎么办?kotlin给我们提供了step关键字:
for(i in 1..10 step 2){
println(i)
}
以上区间都是值增的区间,那么值减的区间如何声明呢?kotlin给我们提供了downTo关键字,用法如下:
for (i in 5 downTo 1){
println(i)
}
需要注意的是这里的downTo是闭区间,即5 downTo 1代表[5,4,3,2,1],同时,downTo也可以配合step使用。
5:面向对象
5.1:类与对象
kotlin中类的声明方法为:
class Animal{
var gender=""
var age=0
fun eat(){
println("$gender is eating")
}
}
上门的代码定义了一个Animal动物类,其有两个属性,一个是gender性别,另一个是age年龄,此外还声明了一个eat方法,代表动物在吃东西。
现在我们可以实例化一个Animal类的对象:
val animal=Animal()
可以看到,kotlin实例化对象的时候不需要像Java那样使用new关键字,直接调用类的构造函数即可。
5.2:继承与构造函数
面向对象编程势必要引入继承,我们举一个例子,我们想构造一个Cat猫类,其继承自Animal动物类,那么首先,我们需要使Animal类变成可被继承的类,在Kotlin中,不是所有类都可以被继承,这也是其与Java比较大的一个区别,kotlin中任何一个非抽象类默认都是不可以被继承的,相当于Java中给类声明了final关键字,注意这里说的是”默认“情况下不可被继承,这是因为Kotlin在设计的时候认为类和变量一样,都应该尽量不被改变,以此保证安全性,那么如何让一个非抽象类变成可被继承的呢?kotlin给我们提供了open关键字,只需要在类前面加上open关键字即可,这样相当于告诉kotlin,我需要让这个类被继承,比如:
open class Animal{
var gender=""
var age=0
fun eat(){
println("$gender is $age years old")
}
}
现在我们就可以创建继承自Animal的Cat类了:
class Cat:Animal(){
val suit=""
}
可以看到,kotlin中是通过:来声明继承关系的,可能会有读者对这里的Animal后面的括号有疑惑,为什么需要带这个括号呢?一定要带吗?这个涉及到kotlin中构造函数的相关知识。
kotlin中将构造函数分为两类:
- 主构造函数
- 次构造函数
每个类默认有一个不带参数的主构造函数(也可以手动给其添加参数),主构造函数没有函数体,比如:
class Animal{
var gender=""
var age=0
fun eat(){
println("$gender is eating")
}
}
就相当于:
class Animal(){
var gender=""
var age=0
fun eat(){
println("$gender is eating")
}
}
因为这里主构造函数没有参数,所以可以把()省略,如果想要给其添加参数,可以:
class Animal(var category:String){
var gender=""
var age=0
fun eat(){
println("$gender is $age years old")
}
}
可能有的同学就有疑惑了,这个主构造函数没有函数体,那如果想在对象初始化时执行一些代码该怎么办呢?kotlin给我们提供了一个init构造体,所有想要安排在主构造函数的逻辑都可以写在里面:
class Animal(var category:String){
init {
println("Animal被实例化")
}
var gender=""
var age=0
fun eat(){
println("$gender is $age years old")
}
}
现在我们就可以解释为什么:
class Cat:Animal(){
val suit=""
}
中Animal()需要带上括号,因为根据继承特性规定,子类需要在构造函数中调用父类的构造函数的,但是我们说kotlin中主构造函数是没有函数体的,那么子类在哪调用父类的构造函数呢?kotlin给出的答案是通过括号来调用,即class Cat:Animal()中,()表示执行Cat的主构造函数时调用父类Animal的主构造函数,所以,就算()中没有参数,也不可以省略。
以上介绍了主构造函数,下面我们来介绍次构造函数。
任何一个类最多只能有一个主构造函数,但是可以有多个次构造函数,次构造函数也可以被用来实例化对象,其是有函数体的,比如:
class Animal(var category: String) {
constructor(category: String, vision: String) : this(category) {
println("这是次构造函数")
}
init {
println("Animal被实例化")
}
var gender = ""
var age = 0
fun eat() {
println("$gender is $age years old")
}
}
可以看到,kotlin中使用constructor声明次构造函数,并且kotlin规定当一个类既有主构造函数又有次构造函数时,次构造函数必须调用主构造函数,如上面的this(category)。
还有一种情况是一个类没有主构造函数,但是有次构造函数,比如:
class Cat : Animal {
constructor(category: String, vision: String) : super(category, vision) {
}
val suit = ""
}
可以看到,首先Cat类没有声明主构造函数,其次,Cat声明了次构造函数,所以Cat是一个没有主构造函数但是有次构造函数的类,既然Cat没有主构造函数,其主构造函数也就不会被执行,所以其就不用规定执行其主构造函数时必须执行父类的构造函数了,所以继承Animal的时候就可以把()去掉,但是在声明Cat的次构造函数的时候,必须通过super调用父类的构造函数。
其实在实践编程时,次构造函数是很少用到的,什么原因呢?想想我们为什么需要次构造函数?当然是为了多一种实例化的方式,比如主构造函数只声明了接收一个参数,现在新需求想要加一个有两个参数的构造函数,所以想到加一个次构造函数来解决问题,kotlin为了解决这个痛点,引入了对参数默认值的支持,比如:
open class Animal(var age:Int) {
constructor(category: String, vision: String):this(10) {
}
}
可以改造为:
open class Animal(var age: Int = 10, category: String, vision: String) {
}
这时我们可以用两种方式实例化Animal的对象:
val a1 = Animal(category = "", vision = "")
val a2 = Animal(age = 20, category = "", vision = "")
5.3:接口
kotlin和java一样,一个类只能最多继承一个类,但是可以实现多个接口,kotlin声明接口的方法如下:
interface Eat {
fun openMouth()
fun closeMouth()
}
可以看到,kotlin使用interface声明接口,并且声明了openMouth和closeMouth两个函数,现在我们就可以让Cat类实现该接口了:
class Cat : Animal,Eat {
override fun openMouth() {
}
override fun closeMouth() {
}
constructor(category: String, vision: String) : super(category, vision) {
}
val suit = ""
}
可以看到,kotlin中实现和继承都是通过:实现的,只需要用,将父类、接口隔开即可。同时,kotlin允许接口中的函数有默认实现,比如:
interface Eat {
fun openMouth()
fun closeMouth() {
println("closeMouth")
}
}
这时实现Eat时只会强制要求实现openMouth()函数,不会强制要求实现closeMouth() 函数。
5.4:可见性修饰符
Java有public、protected、private、default四种可见性修饰符,kotlin中也有四种,分别是public、private、protected、internal,其可见性对比见下表:
这里internal的可见性为同一模块中可见,其应用场景是,比如我们开发了一个模块给别人用,我们希望某个方法只可以被我们本模块自己用,不开放给用户,就可以将其声明为internal。
5.5:数据类与单例类
5.5.1:数据类
什么是数据类?我们所说的MVC、MVP、MVVM等架构模式,其中的M指的就是数据类,那我们一般是如何定义数据类的呢?回想一下Java中数据类的定义方法,这里举个例子:
public class Animal {
int age;
String gender;
@Override
public boolean equals(Object obj) {
if (obj instanceof Animal) {
Animal animal = (Animal) obj;
if (animal.age == this.age && animal.gender == this.gender) {
return true;
}
return false
}
return false;
}
@Override
public int hashCode() {
return gender.hashCode() + age;
}
@Override
public String toString() {
return "age is:" + age + "gender is:" + gender;
}
}
可以看到,Java中定义一个数据类通常需要重写equals()、hashCode()、toString()这几个方法,其用途分别为:
- equals():判断两个数据类是否相等
- hashCode():为了保证HashMap、HashSet等数据结构可以正常工作
- toString():为了提供更清晰的日志
可以看到,Java中实现一个数据类步骤很繁琐,需要写很多没有实际逻辑意义的代码,所以kotlin对此进行了优化,在kotlin中声明一个数据类只需要:data class Animal(val age: Int, val gender: String) 可以看到,只需要在声明类之前加上data关键字,就可以将一个类声明为数据类,kotlin会自动根据主构造函数中的参数帮你将equals()、hashCode()、toString()等固定写法的方法自动生成,我们将上面这行代码的字节码反编译为java代码,可以得到如下结果:
import kotlin.Metadata;
import kotlin.jvm.internal.Intrinsics;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@Metadata(
mv = {1, 1, 13},
bv = {1, 0, 3},
k = 1,
d1 = {"\u0000 \n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0000\n\u0002\u0010\b\n\u0000\n\u0002\u0010\u000e\n\u0002\b\t\n\u0002\u0010\u000b\n\u0002\b\u0004\b\u0086\b\u0018\u00002\u00020\u0001B\u0015\u0012\u0006\u0010\u0002\u001a\u00020\u0003\u0012\u0006\u0010\u0004\u001a\u00020\u0005¢\u0006\u0002\u0010\u0006J\t\u0010\u000b\u001a\u00020\u0003H?\u0003J\t\u0010\f\u001a\u00020\u0005H?\u0003J\u001d\u0010\r\u001a\u00020\u00002\b\b\u0002\u0010\u0002\u001a\u00020\u00032\b\b\u0002\u0010\u0004\u001a\u00020\u0005H?\u0001J\u0013\u0010\u000e\u001a\u00020\u000f2\b\u0010\u0010\u001a\u0004\u0018\u00010\u0001H?\u0003J\t\u0010\u0011\u001a\u00020\u0003H?\u0001J\t\u0010\u0012\u001a\u00020\u0005H?\u0001R\u0011\u0010\u0002\u001a\u00020\u0003¢\u0006\b\n\u0000\u001a\u0004\b\u0007\u0010\bR\u0011\u0010\u0004\u001a\u00020\u0005¢\u0006\b\n\u0000\u001a\u0004\b\t\u0010\n¨\u0006\u0013"},
d2 = {"LAnimal;", "", "age", "", "gender", "", "(ILjava/lang/String;)V", "getAge", "()I", "getGender", "()Ljava/lang/String;", "component1", "component2", "copy", "equals", "", "other", "hashCode", "toString", "LearnKotlin"}
)
public final class Animal {
private final int age;
@NotNull
private final String gender;
public final int getAge() {
return this.age;
}
@NotNull
public final String getGender() {
return this.gender;
}
public Animal(int age, @NotNull String gender) {
Intrinsics.checkParameterIsNotNull(gender, "gender");
super();
this.age = age;
this.gender = gender;
}
public final int component1() {
return this.age;
}
@NotNull
public final String component2() {
return this.gender;
}
@NotNull
public final Animal copy(int age, @NotNull String gender) {
Intrinsics.checkParameterIsNotNull(gender, "gender");
return new Animal(age, gender);
}
// $FF: synthetic method
@NotNull
public static Animal copy$default(Animal var0, int var1, String var2, int var3, Object var4) {
if ((var3 & 1) != 0) {
var1 = var0.age;
}
if ((var3 & 2) != 0) {
var2 = var0.gender;
}
return var0.copy(var1, var2);
}
@NotNull
public String toString() {
return "Animal(age=" + this.age + ", gender=" + this.gender + ")";
}
public int hashCode() {
int var10000 = this.age * 31;
String var10001 = this.gender;
return var10000 + (var10001 != null ? var10001.hashCode() : 0);
}
public boolean equals(@Nullable Object var1) {
if (this != var1) {
if (var1 instanceof Animal) {
Animal var2 = (Animal)var1;
if (this.age == var2.age && Intrinsics.areEqual(this.gender, var2.gender)) {
return true;
}
}
return false;
} else {
return true;
}
}
}
可以看到,kotlin在编译的时候帮我们自动完成了equals()、hashCode()、toString()等函数,为我们减少了开发的工作量。
另外你应该也注意到了,当一个类中没有代码时可以将大括号省略,比如可以将:
data class Animal(val age: Int, val gender: String){
}
简化为:
data class Animal(val age: Int, val gender: String)
5.5.2:单例类
单例可以说是日常开发中常见的需求了,很多时候我们希望构建一个全局最多只有一个实例的类,在Java中一般会这么写:
public class Animal {
private static Animal animal;
private Animal() {
}
public synchronized static Animal getInstance() {
if (animal == null) {
animal = new Animal();
}
return animal;
}
}
可以看到写法还是繁琐的,在kotlin中只需要:
object Animal {
fun testFun() {
}
}
没错又是只有一行代码,kotlin中使用object关键字来声明单例,那么其实现原理是什么呢?我们看看上面代码的字节码反编译为java的结果是什么:
import kotlin.Metadata;
@Metadata(
mv = {1, 1, 13},
bv = {1, 0, 3},
k = 1,
d1 = {"\u0000\u0012\n\u0002\u0018\u0002\n\u0002\u0010\u0000\n\u0002\b\u0002\n\u0002\u0010\u0002\n\u0000\b?\u0002\u0018\u00002\u00020\u0001B\u0007\b\u0002¢\u0006\u0002\u0010\u0002J\u0006\u0010\u0003\u001a\u00020\u0004¨\u0006\u0005"},
d2 = {"LAnimal;", "", "()V", "testFun", "", "LearnKotlin"}
)
public final class Animal {
public static final Animal INSTANCE;
public final void testFun() {
}
private Animal() {
}
static {
Animal var0 = new Animal();
INSTANCE = var0;
}
}
可以看到,object关键字的背后是kotlin为我们自动实现了一套饿汉式的单例代码。使用该单例类也很简单:
Animal.testFun()
可以看到,直接通过类名调用方法即可。
6:总结
本文我们介绍了Kotlin的基础知识,涉及到变量和函数、程序的逻辑控制、面向对象等知识点,希望大家可以熟练掌握,下一篇文章我们将介绍kotlin的一些高级特性,比如lambda编程、标准函数和静态方法、拓展函数、高阶函数等知识点,欢迎大家关注。
相关推荐
- Python自动化脚本应用与示例(python办公自动化脚本)
-
Python是编写自动化脚本的绝佳选择,因其语法简洁、库丰富且跨平台兼容性强。以下是Python自动化脚本的常见应用场景及示例,帮助你快速上手:一、常见自动化场景文件与目录操作...
- Python文件操作常用库高级应用教程
-
本文是在前面《Python文件操作常用库使用教程》的基础上,进一步学习Python文件操作库的高级应用。一、高级文件系统监控1.1watchdog库-实时文件系统监控安装与基本使用:...
- Python办公自动化系列篇之六:文件系统与操作系统任务
-
作为高效办公自动化领域的主流编程语言,Python凭借其优雅的语法结构、完善的技术生态及成熟的第三方工具库集合,已成为企业数字化转型过程中提升运营效率的理想选择。该语言在结构化数据处理、自动化文档生成...
- 14《Python 办公自动化教程》os 模块操作文件与文件夹
-
在日常工作中,我们经常会和文件、文件夹打交道,比如将服务器上指定目录下文件进行归档,或将爬虫爬取的数据根据时间创建对应的文件夹/文件,如果这些还依靠手动来进行操作,无疑是费时费力的,这时候Pyt...
- python中os模块详解(python os.path模块)
-
os模块是Python标准库中的一个模块,它提供了与操作系统交互的方法。使用os模块可以方便地执行许多常见的系统任务,如文件和目录操作、进程管理、环境变量管理等。下面是os模块中一些常用的函数和方法:...
- 21-Python-文件操作(python文件的操作步骤)
-
在Python中,文件操作是非常重要的一部分,它允许我们读取、写入和修改文件。下面将详细讲解Python文件操作的各个方面,并给出相应的示例。1-打开文件...
- 轻松玩转Python文件操作:移动、删除
-
哈喽,大家好,我是木头左!Python文件操作基础在处理计算机文件时,经常需要执行如移动和删除等基本操作。Python提供了一些内置的库来帮助完成这些任务,其中最常用的就是os模块和shutil模块。...
- Python 初学者练习:删除文件和文件夹
-
在本教程中,你将学习如何在Python中删除文件和文件夹。使用os.remove()函数删除文件...
- 引人遐想,用 Python 获取你想要的“某个人”摄像头照片
-
仅用来学习,希望给你们有提供到学习上的作用。1.安装库需要安装python3.5以上版本,在官网下载即可。然后安装库opencv-python,安装方式为打开终端输入命令行。...
- Python如何使用临时文件和目录(python目录下文件)
-
在某些项目中,有时候会有大量的临时数据,比如各种日志,这时候我们要做数据分析,并把最后的结果储存起来,这些大量的临时数据如果常驻内存,将消耗大量内存资源,我们可以使用临时文件,存储这些临时数据。使用标...
- Linux 下海量文件删除方法效率对比,最慢的竟然是 rm
-
Linux下海量文件删除方法效率对比,本次参赛选手一共6位,分别是:rm、find、findwithdelete、rsync、Python、Perl.首先建立50万个文件$testfor...
- Python 开发工程师必会的 5 个系统命令操作库
-
当我们需要编写自动化脚本、部署工具、监控程序时,熟练操作系统命令几乎是必备技能。今天就来聊聊我在实际项目中高频使用的5个系统命令操作库,这些可都是能让你效率翻倍的"瑞士军刀"。一...
- Python常用文件操作库使用详解(python文件操作选项)
-
Python生态系统提供了丰富的文件操作库,可以处理各种复杂的文件操作需求。本教程将介绍Python中最常用的文件操作库及其实际应用。一、标准库核心模块1.1os模块-操作系统接口主要功能...
- 11. 文件与IO操作(文件io和网络io)
-
本章深入探讨Go语言文件处理与IO操作的核心技术,结合高性能实践与安全规范,提供企业级解决方案。11.1文件读写11.1.1基础操作...
- Python os模块的20个应用实例(python中 import os模块用法)
-
在Python中,...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
因果推断Matching方式实现代码 因果推断模型
-
git pull命令使用实例 git pull--rebase
-
面试官:git pull是哪两个指令的组合?
-
git 执行pull错误如何撤销 git pull fail
-
git pull 和git fetch 命令分别有什么作用?二者有什么区别?
-
git fetch 和git pull 的异同 git中fetch和pull的区别
-
git pull 之后本地代码被覆盖 解决方案
-
还可以这样玩?Git基本原理及各种骚操作,涨知识了
-
git命令之pull git.pull
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)