文档章节

面向对象编程

huijue
 huijue
发布于 08/19 12:26
字数 1827
阅读 38
收藏 0

1、类和对象

类是对象的蓝图和模板,而对象是实例;即对象是具体的实例,类是一个抽象的模板

当我们把一大堆拥有共同特征的对象的静态特征(属性)和动态特征(行为)都抽取出来后,就可以定义出一个叫做“类”的东西

class Student(object):
	#__init__是一个特殊方法用于在创建对象时进行初始化操作
	#通过这个方法我们可以为学生对象绑定name和age两个属性
	def __init__(self, name, age):
		self.name = name
		self.age = age
	def study(self, course_name):
		print('%s正在学习%s.' % (self.name,course_name))
	# PEP 8要求标识符的名字用全小写多个单词用下划线链接
	# 但是部分程序员和公司倾向于使用驼峰命名法(驼峰标识)
	def watch_movie(self):
		if self.age < 18:
			print('%s只能观看《熊出没》.' %self.name)
		else:
			print('%s正在观看岛国爱情大电影.'%self.name)
if __name__ == '__main__':
	s = Student('Chengxin', 25)
	print(s.study('English'))
	print(s.watch_movie())

PS:类实例时,需要传入创建对象初始化时的值

       类中的方法类似于函数,不过第一参数必须是self,self代表类本身

 

2、类访问可见性问题

class Test:
	def __init__(self, foo):
		self.__foo = foo

	def __bar(self):
		print(self.__foo)
		print('__bar')

def main():
	test = Test('hello')
	# AttributeError:'Test' object has no attribute '__bar'
	test._Test__bar()
	#test.__bar()
	# AttributeError: 'Test' object has no attribute '__foo'
	print(test._Test__foo)
	# 因为test.__foo是不能直接访问到私密属性的,所以必须在前面加上_类名才可以
	# such as test._Test__foo

if __name__ == "__main__":
	main()

--------------------------------------------------------------------
下面是单下划线命名
--------------------------------------------------------------------
class Test:
	def __init__(self, foo):
		self._foo = foo

	def __bar(self):#方法的私密定义
		print(self._foo)
		print('__bar')

def main():
	test = Test('hello')
	# AttributeError:'Test' object has no attribute '__bar'
	test._Test__bar()
	#test.__bar()
	# AttributeError: 'Test' object has no attribute '__foo'
	print(test._foo)
	# 因为test.__foo是不能直接访问到私密属性的,所以必须在前面加上_类名才可以
	# such as test._Test__foo

if __name__ == "__main__":
	main()

实际开发中,我们并不建议将属性设置为私有的,因为这会导致子类无法访问。所以大多数Python程序员会遵循一种命名惯例就是让属性名以单下划线开头来表示属性是受保护的,本类之外的代码在访问这样的属性时应该要保持慎重

问题:私密属性的设置是否前面是单下划线_还是双下划线__

 

3、封装、继承和多态

封装:隐藏一切可以隐藏的实现细节,只向外界暴露(提供)简单的编程接口

          我们在类中定义的方法其实就是把数据和对数据的操作封装起来了,在我们创建了对象之后,只需要给对象发送一个消息(调用方法)就可以执行方法中的代码,也就是说我们只需要知道方法的名字和传入的参数(方法的外部视图),而不需要知道方法内部的实现细节(方法的内部视图)。

 

4、@property装饰器

类的定义中属性命名以单下划线方式来暗示属性是受保护的,不建议外界直接访问

如果想访问属性可以通过属性的getter(访问器)和setter(修改器)方法进行对应的操作

如果要做到这点,就可以考虑使用@prooerty包装其来包装getter和setter方法,使得对属性的访问既安全又方便

class Person(object):

    def __init__(self, name, age):
        self._name = name
        self._age = age

    # 访问器 - getter方法
    @property
    def name(self):
        return self._name

    # 访问器 - getter方法
    @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)


def main():
    person = Person('王大锤', 12)
    person.play()
    person.age = 22
    person.play()
    # person.name = '白元芳'  # AttributeError: can't set attribute


if __name__ == '__main__':
    main()

 

5、__slots__魔法

Python是一门动态语言。

动态语言允许我们在程序运行时给对象绑定新的属性或方法,

也可以对已经绑定的属性和方法进行解绑定

通过在类中定义__slots__变量来进行限定,对象只能绑定某些属性

ps:_slots__的限定只对当前类的对象生效,对子类并不起任何作用。

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 = '男'
    # AttributeError: 'Person' object has no attribute '_is_gay'
    # person._is_gay = True

 

6、静态方法和类方法

写在类中的方法并不都是对象方法

eg:我们定义一个“三角形”类,通过传入三条边长来构造三角形,并提供计算周长和面积的方法

但首先要考虑的是传入的三条边是否能够构成三角型对象,这时就可以先写一个方法来验证三条边长是否可以构成三角形

这个方法是类方法,在调用这个方法时三角形对象尚未创建出来,

静态方法是属于三角形类而不属于三角型对象的

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))


def main():
    a, b, c = 3, 4, 5
    # 静态方法和类方法都是通过给类发消息来调用的
    if Triangle.is_valid(a, b, c):
        t = Triangle(a, b, c)
        print(t.perimeter())
        # 也可以通过给类发消息来调用对象方法但是要传入接收消息的对象作为参数
        # print(Triangle.perimeter(t))
        print(t.area())
        # print(Triangle.area(t))
    else:
        print('无法构成三角形.')


if __name__ == '__main__':
    main()

 

类方法

类方法和静态方法类似,Python还可以在类中定义类方法,类方法的第一个参数约定名为cls,它代表的是当前类相关的信息

的对象(类本身也是一个对象,有的地方也称之为类的元数据对象),通过这个参数我们可以获取和相关的信息并且可以创建出

类的对象,代码如下所示。

class People(object):
    country = 'china'
    #类方法,用classmethod来进行修饰
    @classmethod
    def getCountry(cls):
        return cls.country
p = People()
print(p.getCountry())
print(People.getCountry())

 

类方法的一个功能就是对类的属性进行修改


class People(object):
    country = 'china'
    #类⽅法,⽤classmethod来进⾏修饰
    @classmethod
    def getCountry(cls):
        return cls.country
    @classmethod
    def setCountry(cls,country):
        cls.country = country
p = People()
print p.getCountry() #可以⽤过实例对象引⽤
print People.getCountry() #可以通过类对象引⽤
p.setCountry('japan')
print p.getCountry()
print People.getCountry()

 

本文转载自:https://github.com/jackfrued/Python-100-Days/blob/master/Day01-15/09.%E9%9D%A2%E5%90%91%E5%AF%B9%...

huijue
粉丝 0
博文 7
码字总数 686
作品 0
南京
私信 提问
函数式和面向对象编程有什么区别?

函数式编程 (Functional Programming) 和 面向对象编程 (Object Oriented Programming) 是两个主流的编程范式,他们有各自独特的闪光点,比如函数式编程的数据不可变、惰性求值,面向对象编程...

闭眼卖布
07/02
0
0
Java学习之面向对象与面向过程的比较

前言 Java编程语言是一门面向对象的语言,这与之前的编程语言来说,是一个重大的进步和发展,下面主要来分析一下面向对象和面向过程两者之间的关系。 编程语言的发展 如下图,编程语言的发展...

m18633778874
2018/04/10
0
0
OOA、OOD和OOP的定义及之间的关系

什么是面向对象分析(OOA)? "面向对象分析是一种分析方法,这种方法利用从问题域的词汇表中找到的类和对象来分析需求。" 什么是面向对象设计(OOD)? “面向对象设计是一种设计方法,包括面向对...

雲克
2013/01/22
7.1K
0
面向对象编程从骨子里就有问题——看看名人大家是如何吐槽面向对象的

本文由“外刊IT评论”网(www.aqee.net)荣誉出品 “面向对象编程是一个极其糟糕的主意,只有硅谷里的人能干出这种事情。” — Edsger Dijkstra(图灵奖获得者) “面向对象设计是用罗马数字做计...

罪恶的花生
2013/07/02
271
6
代码为什么那么乱! 换种方法学面向对象

点击关注 异步图书,置顶公众号 每天与你分享 IT好书 技术干货 职场知识 点击此处购书 参与文末话题讨论,每日赠送异步图书 ——异步小编 我们经常会为一个问题寻找多种不同的解决方案。当你...

异步社区
2018/05/15
0
0

没有更多内容

加载失败,请刷新页面

加载更多

查看线上日志常用命令

cat 命令(文本输出命令) 通常查找出错误日志 cat error.log | grep 'nick' , 这时候我们要输出当前这个日志的前后几行: 显示file文件里匹配nick那行以及上下5行 cat error.log | grep -C ...

xiaolyuh
15分钟前
3
0
六、Java设计模式之工厂方法

工厂方法定义: 定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行 类型:创建型 工厂方法-使用场景: 创建对象需要大量重复的代码 ...

东风破2019
22分钟前
2
0
win服务器管理遇到的一系列问题记录

有些小伙伴在使用iis7远程桌面管理工具的时候总是会遇到一系列的问题,下面就是为大家介绍一下服务器日常管理过程中出现的问题及我的解决办法和心得。希望能帮到大家。   拒绝服务器重新启...

1717197346
29分钟前
2
0
flutter 剪切板 复制粘贴

复制粘贴功能 import 'package:flutter/services.dart'; Clipboard.setData(ClipboardData(text:_text));Clipboard.getData;...

zdglf
32分钟前
3
0
如何保证消息的可靠性传输?或者说,如何处理消息丢失的问题?

面试题 如何保证消息的可靠性传输?或者说,如何处理消息丢失的问题? 面试官心理分析 这个是肯定的,用 MQ 有个基本原则,就是数据不能多一条,也不能少一条,不能多,就是前面说的重复消费...

米兜
32分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部