前言
python的最大特点就是dynamically typed就是动态类型,不像java需要定义数据类型
引入
先从一段代码引入:
1
2
3
4
5
6
7
8
9
10class Dog():
def __init__(self,name,age):
self.name=name
self.age=age
def getName(self):
return self.name
dog=Dog('name',16)
print(dog.getName())
别急,我们先学习下py的函数,这个形式跟C以及java等语言有点不一样。跨度有点大,对于刚接触来说,我们需要对比一下。
自定义函数
先来看一个例子
1
2
3
4
5def my_func(message):
print('Got a messag: {}'.format(message))
my_func('hello world')
#这里其实我有个地方不是很懂,不过大约能够知道什么意思,就是{}用来占位,记得在java中log常常这么用
大致形式
1
2
3def 函数名(参数):
处理
return/yeild
与其他语言不一样的是,def是可执行语句,即函数被调用前,都是不存在的,直到被调用的时候才会创建一个新的函数对象,并赋予其名字
对于以上这段话不理解的我们需要对比以下代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14hello()
def hello():
print('hello')
return
#报错,在主程序里,函数要先于调用前的定义
def my_func():
hello()
return
def hello():
print('hello')
return
my_func()
#正常运行,因为def是可执行语句,在调用的时候都不存在,但是我们必须保证调用前都已经声明定义了
注:我们先有个全局的概念,然后我们在看一下细节
我们深入来看一个代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15def my_func(l):
if not isinstance(l,list):
print('what you input is not a list')
return
if len(l)==0:
print('waht you input is empty')
return
largest=l[0]
for item in l:
if item>largest:
largest=item
print('the largest item in l is {}'.format(largest))
return
my_func([8,-1,0,2])
多态
看到这个我真的哭了,这里的多态完全跟java不同
1
2
3
4
5
6
7def my_sum(a,b):
print(a+b)
return
my_sum(1,2)
my_sum([1,2],[3,4])
my_sum('hello','world')
#对于这种来什么就接受什么的函数,必要时需要在前面进行类型检查
函数变量的作用域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
27MAX_VALUE=100
def test1(value):
global MAX_VALUE
MAX_VALUE=value
print(MAX_VALUE)
return
def test2(value):
MAX_VALUE=value
print(MAX_VALUE)
return
def test3():
print(MAX_VALUE)
return
test3()
test2(1)
test3()
test1(1)
test3()
----
输出结果:
100
1
100
1
1
分析一下:
函数内部默认为局部变量,即当函数调用结束后(return),该变量会被收回,并且不能够被访问
Python的全局变量定义在主程序中
函数可以调用全局变量,如果用更改全局变量的时候需要 global关键字,这里并不是重新创建一个新的变量,而是告诉Python 解释器,这里的变量就是之前定义的全局变量
如果函数内部的变量名与主程序的变量名重名,那么局部变量将覆盖全局变量
现在我们基本上了解了python的函数基本规则,我们回到类
1
2
3
4
5
6
7
8
9
10class Dog():
def __init__(self,name,age):
self.name=name
self.age=age
def getName(self):
return self.name
dog=Dog('name',16)
print(dog.getName())
在这里我们对比java的dog类如何去定义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public class Dog{
private String name;
private int age;
Dog(String name,int age){
this.name=name;
this.age=age;
}
String getName(){
return this.name;
}
public static void main(String...ags){
Dog dog=new Dog("name",16);
System.out.println(dog.getName());
}
}
这两段代码执行的效果是一样的。
区别:
python不需要提前声明的类的属性,因为不要指明属性的数据类型
Python的构造函数不是以类名,虽然调用的时候是以类名,说明在声明定义该类的对象的时候,会自动调用Init函数
注意到python的每个函数里面都有一个变量self,但是在调用的时候又不需要传入该参数,你可以看到这个self的作用跟this的作用差不多,只不过在python中必须使用这个self,在每一个类的方法中,self总是指向当前的实例,在init函数中self指向的最新被创建的对象,在其他函数中,指向调用该方法的对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14class Dog():
def __init__(self,name,age):
self.__name=name
self.age=age
self.__sex='boy'
def getName(self):
return self.__name
dog=Dog('name',16)
dog.__name='Name'
print(dog.__name)
print(dog.getName())
print(dog.__sex)
注:在一次被python的数据定义给坑了
首先我们注意到java里面数据是由private属性的,那么在python中默认以两个下划线表示该属性为私有属性,不可被对象之间调用
但是如果dog.__name记住这里的name属性不是该类的属性,而是你给dog这个变量重新定义的一个,与类里定义的不同
接着我们深入了解面向对象里面的细节,先来看一下下面这段代码
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
28class Dog():
MAX_AGE=16
def __init__(self,name,age):
self.name=name
self.age=age
@classmethod
def newName(cls,name):
cls.name=name
return
def getName(self):
return self.name
@staticmethod
def get_MAX_AGE(age):
if age
print("the dog age is {}".format(age))
return
else:
print('the maxage is {}'.format(Dog.MAX_AGE))
return
dog=Dog('NAME',14)
print(dog.getName())
dog.newName('name')
print(dog.getName())
dog.get_MAX_AGE(16)
第一个MAX_AGE是类中定义的常量,可以通过self.MAX_AGE或者Entity.MAX_AGE调用
注意到 @classmethod和@staticmethod 我们已经将类中的函数区别开来了,首先是classmethod类函数,能够动态访问或者修改对象的属性,其第一个参数一般为cls,最常用的功能是实现不用的init构造函数(好吧,上述代码不具有参考意义) ,@staticmehod是静态函数,可以用来做一些简单独立的任务,像什么测试等等,最后就是成员函数,是最正常的函数,不需要任何声明,第一个self代表当前对象的引用
写到最后
这样,已经大致的会写python的类了,但是面向对象里面还有个重要的思想就是继承。不过这个留到后面来深入。当前我的目标就是对python基础有个全貌的了解。