虽然看到我文章的人不多呀,但还是要说一声抱歉呀,因为考研的事情耽误了很久,并且之前学的很多东西也都有丢下。最近我会不定时的补一些东西。
就在前天刚刚结束开题报告,然后复盘了一下python中的一些内容,发现python虽然是一款入门较为轻松的开发语言,但是现在网上可以找到的一些教程,对于python面向对象
这一方面的介绍却并不多。所以本人准备分享一些我的学习经验呀。
====================================================
什么是面向对象
首先是比较正式的定义:“把一组数据结构和处理它们的方法组成对象(object),把相同行为的对象归纳为类(class),通过类的封装(encapsulation)隐藏内部细节,通过继承(inheritance)实现类的特化(specialization)和泛化(generalization),通过多态(polymorphism)实现基于对象类型的动态分派。”
这里呢我就用我自己的理解来解释一下:
与面向对象
相对应的是面向过程
,如果我们饿了,我们需要去做饭:买菜、准备调料、起锅烧油、装盘、吃、刷碗等等这一系列的过程就是面向过程
,我们在经历了这一系列的过程之后才算是完成吃饭这个动作
。面向对象
就是将吃饭的一系列过程进行实体化
,一个‘吃饭’
就代表我们已经完成了上述的所有过程,但是具体怎么实现的就不是我们需要考虑的内容。
Python中如何实现面向对象
一、类
这里的类就是我在上述解释中的实体,但是我们需要知道的是类只能算是一种抽象概念
,我们想要用我们定义的类去做一些事情的话就需要把这个类进行现实化–创建对象
。下面先来看一段代码。
class Student(object):
def __init__(self, name, age):
self.name = name
self.age = age
def study(self, course_name):
print('%s正在学习%s. ' % (self.name, course_name))
- 这里就是创建了一个学生类,第一个函数(暂时叫做函数)就相当于Java中的初始化函数,在使用这个类创建对象时需要传递的参数,可以在这里进行体现。
- 第二个函数定义了这个学生在学习,传递的参数是“课程”,如果我们想要定义更多的事情,则可以创建更多的函数。
二、安全性
想不到吧,类就是这么简单,上面这就是创建了一个类。但是只要一提到类我们就需要注意安全性
这个问题。因为如果所有人都可以直接操作类中参数,那程序的安全性就无法得到保障了,但是在Python中貌似没有类似于Java中的protect、public等关键字对函数或者是变量进行声明,那我们应该怎么做呢?
class Test(object):
def __init__(self, foo):
self.__foo = foo
def __bar(self):
print(self.__foo)
print('__bar')
- 在属性或者函数前面加上__或者_就代表它不能被直接访问。
class Test(object):
def __init__(self, foo):
self.__foo = foo
def __bar(self):
print(self.__foo)
print('__bar')
def main_two():
test = Test('hello')
# 无法直接打印出来test.__foo或者test__bar
test._Test__bar()
print(test)
if __name__ == '__main__':
main_two()
- 对上述代码就行运行,我们直接打印
test.__foo
或者test.__bar
是会报错的 - 使用
test._Test__bar()
可以进行操作。
在Java中我们设置了有set和get方法对属性进行获取或者修改,在Python中也有类似的操作。
class Person(object):
def __init__(self, name, age):
self._name = name
self._age = age
# 访问器 - getter方法
@property
def name(self):
return self._name
@property
def age(self):
return self._age
# 修改器 - setter方法
@age.setter
def age(self, age):
self._age = age
def play(self):
if self._age <= 16:
print('%s正在玩飞行棋.' % self._name)
else:
print('%s正在玩斗地主.' % self._name)
- 这个其实没啥好说的,大家看一下的就能看出门道来,
@property
定义的就是get
方法,@age.setter
定义的就是age
这个属性的set
方法。
除了上述方法,我们还可以通过__slot__
方法对对象进行属性绑定。
class Person(object):
# 限定Person对象只能绑定_name, _age和_gender属性
__slots__ = ('_name', '_age', '_gender')
def __init__(self, name, age):
self._name = name
self._age = age
@property
def name(self):
return self._name
@property
def age(self):
return self._age
@age.setter
def age(self, age):
self._age = age
def play(self):
if self._age <= 16:
print('%s正在玩飞行棋.' % self._name)
else:
print('%s正在玩斗地主.' % self._name)
def main():
person = Person('王大锤', 22)
person.play()
person._gender = '男'
# 若不限定的话,python不会报错
person._is_gay = True
if __name__ == '__main__':
main()
- 上述的
Person
对象我们只对其绑定了三个属性,所以当我们打印person._is_gay
时就会报错,因为Person
中没有绑定_is_agy
这个属性。 - 如果我们不使用
__slot__
方法时,进行person._is_gay = True
时是不会出错的,并且会为当前已经创建的对象添加_is_gay
属性。
静态类和类方法
在Java中我们都是使用static
进行静态方法的定义的,在python中这么定义:
from math import sqrt
class Triangle(object):
def __init__(self, a, b, c):
self._a = a
self._b = b
self._c = c
@staticmethod
def is_valid(a, b, c):
return a + b > c and b + c > a and a + c > b
def perimeter(self):
return self._a + self._b + self._c
def area(self):
half = self.perimeter() / 2
return sqrt(half * (half - self._a) * (half - self._b) * (half - self._c))
@staticmethod
下面定义的方法就是静态方法了。静态方法的直观好处就是可以不用先创建对象再调用方法,直接一个Triangle.is_valid(a, b, c)
即可调用相应的功能。
接下来说类方法:
from time import time, localtime, sleep
class Clock(object):
def __init__(self, hour=0, minute=0, second=0):
self._hour = hour
self._minute = minute
self._second = second
@classmethod
def now(cls):
ctime = localtime(time())
return cls(ctime.tm_hour, ctime.tm_min, ctime.tm_sec)
- 使用
@classmethod
标注的方法就是类方法。使用clock = Clock.now()
可以直接调用now()
这个方法同时返回一个对象给clock
继承、多态、抽象
python中的继承和多态与Java并没有什么实质上的差别,只是实现方式不同。我们直接看例子:
class Person(object):
def __init__(self, name, age):
self._name = name
self._age = age
@property
def name(self):
return self._name
@property
def age(self):
return self._age
@age.setter
def age(self, age):
self._age = age
def play(self):
print('%s正在愉快的玩耍.' % self._name)
def watch_av(self):
if self._age >= 18:
print('%s正在观看爱情动作片.' % self._name)
else:
print('%s只能看《熊出没》.' % self._name)
class Student(Person):
def __init__(self, name, age, grade):
super().__init__(name, age)
self._grade = grade
@property
def grade(self):
return self._grade
@grade.setter
def grade(self, grade):
self._grade = grade
def study(self, course):
print('%s的%s正在学习%s.' % (self._grade, self._name, course))
class Teacher(Person):
def __init__(self, name, age, title):
super().__init__(name, age)
self._title = title
@property
def title(self):
return self._title
@title.setter
def title(self, title):
self._title = title
def teach(self, course):
print('%s%s正在讲%s.' % (self._name, self._title, course))
def main():
stu = Student('王大锤', 15, '初三')
stu.study('数学')
stu.watch_av()
t = Teacher('骆昊', 38, '砖家')
t.teach('Python程序设计')
t.watch_av()
if __name__ == '__main__':
main()
- 我们可以体会到,平时我们再创建类时传递的参数都是
object
,但是我们对Person
这个类进行继承形成新的子类时传递的参数时Person
。 - 在子类中我们可以继承父类中的方法,并且可以定义属于自己的方法。
我们想要实现抽象的话需要导入一个包from abc import ABCMeta, abstractmethod
,例子如下:
from abc import ABCMeta, abstractmethod
# 抽象和继承
class Pet(object, metaclass=ABCMeta):
def __init__(self, nickname):
self._nickname = nickname
@abstractmethod
def make_voice(self):
pass
class Dog(Pet):
def make_voice(self):
print('%s:汪汪汪...' % self._nickname)
class Cat(Pet):
"""猫"""
def make_voice(self):
print('%s: 喵...喵...' % self._nickname)
def main():
pets = [Dog('旺财'), Cat('凯蒂'), Dog('大黄')]
for pet in pets:
pet.make_voice()
if __name__ == '__main__':
main()
- 这里的抽象和Java中也是相同的,我们在定义接口时并不对接口进行实现,而是在创建的时候才对其具体功能进行实现。
以上都是我对最近复盘python
的内容时做的一些归纳,并不系统,大家在学习的时候如果发现不对的地方希望可以指正。面向对象说白了就是这么多内容,大家可以结合着Java一起进行学习,如果遇到问题的话也可以对我进行私信,大家共同学习。