Python入门之面向对象编程(二)python类的详解
本文通过创建几个类来覆盖python中类的基础知识,主要有如下几个类
- Animal :各种属性、方法以及属性的修改
- Dog :将方法转化为属性并操作的方法
- Cat :私人属性讲解,方法的继承与覆盖
- Tiger :子类定义时调用父类方法(super的使用)
Animal
python中的一个类中有属性和方法,而二者都分为很多种类型,如下所示
- 属性分为普通属性和类属性
- 方法分为普通方法、类方法、静态方法。
- 具体定义方法和使用见下面的代码和注释,各个属性和方法的使用习惯等见最后的 print_animal 函数打印出的结果
下面是类的定义
class Animal: # 这里是属性定义
actually = "animal" # 类属性 def __init__(self, name, age): # 定义实例时,放在括号里的才要指定
self.name = name # 普通属性,要在__init__方法中定义
self.age = age # 下面是方法的定义
def sleep(self): # 普通方法
print(self.name, "is sleeping") def eat(self, food): # 普通方法,另带参数
print(self.name, "is eating", food) @classmethod
def sentence(cls, adv): # 类方法,使用装饰器变成类方法
print("I am", adv, "an", cls.actually) @staticmethod
def other(person, do): # 静态方法
print(person, "is", do+"ing") @staticmethod
def print_animal():
print("这是之后定义子类的父类,主要讲解最基本的属性、方法以及属性的修改")
print("类属性actually:属于整个类,每个实例都有的属性,内容相同,创建实例时不需要指定,类和实例都可以调用")
print("普通属性name age:属于各个实例,用于存储实例数据") print("普通方法sleep eat:由对象调用,至少一个参数self")
print("类方法sentence:由类、实例调用,至少一个参数cls,可以引用类属性")
print("静态方法other:类中的普通函数,可由类、实例调用") print("修改类属性:用类调用修改,所有实例都更改;用实例调用修改不影响类和其他实例")
print("修改普通属性:直接赋值即可")
创建实例
# 创建实例调用Animal类
adams = Animal(name="Adams",age=2) # 创建实例
adams.actually # 调用类属性
# 'animal'
Animal.actually # 类调用类属性
# 'animal'
adams.name # 调用普通属性
# 'Adams' adams.sleep() # 调用普通方法
# Adams is sleeping
adams.eat("meat") # 有参数的普通方法
# Adams is eating meat adams.sentence("really") # 实例调用类方法
# I am really an animal
Animal.sentence("actually") # 类调用类方法
# I am actually an animal adams.other("Tim", "play") # 实例调用静态方法
# Tim is playing
Animal.other("Mary", "watch") # 类调用静态方法
# Mary is watching Animal.actually = "Animal" # 修改类属性
adams.actually
# 'Animal'
adams.actually = "animal"
Animal.actually
# 'Animal'
adams.age = 3 # 普通属性这样就改过来了 Animal.print_animal()
Dog
Dog类是Animal的一个子类,主要讲解三个装饰器进行方法向属性的转换。
转换有两个主要的好处
- 一是调用没有参数的方法时不再需要加括号,这样的方法就可以当做属性来看
- 二是这样定义的属性赋值时可以进行判断,防止无效属性的产生
这样的转换有两种方式
- 一种是通过@property装饰器,这个装饰器系列一共三个,如果只是想调用这个方法可以只使用@property这个装饰器
- 一种是通过property函数
下面是一个例子,一些说明可以在最后面定义的print_dog方法中查看
class Dog(Animal): # 类的继承 # 只使用@property装饰器与普通函数做对比
def eating(self):
print("I am eating") @property # 用这个装饰器后这个方法调用就可以不加括号,即将其转化为属性
def running(self):
if self.age >= 3 and self.age < 130:
print("I am running")
elif self.age > 0 and self.age <3:
print("I can't run")
else:
print("please input true age") # 三种装饰器,可以获取、设置、删除这样定义的属性
@property
def country(self):
return self._country # 注意这个属性之前从来没有定义过,是在下面的setter中定义的 @country.setter # 用 函数名.setter 的装饰器
def country(self, value): # 设置这个属性的值
self._country = value @country.deleter
def country(self):
print("The attr country is deleted") # 用property函数实现和装饰器相同的功能
def get_city(self):
return self._city def set_city(self, value):
self._city = value def del_city(self, value):
del self._city city = property(get_city, set_city, del_city, "where it is in") @staticmethod
def print_dog():
print("这是Animal的一个子类,主要讲解三个装饰器进行方法向属性的转换")
print("类继承,创建实例时仍要指定父类的普通属性")
print("@property装饰器将方法转化为属性方式调用,此时的方法必须只有一个self参数")
print("使用@property后可以看做一个属性(country),用property函数可以达到相同的效果(city)")
print("注:city中property第四个参数只是一个说明,用Dog.city.__doc__来调用,即返回 where it is in")
创建实例
david = Dog("David", 2) # 创建实例 # 只用@property的情形
david.eating() # 调用普通方法
# I am eating
david.running # 用过@property装饰器后不需要加括号
# I can't run dean = Dog("Dean", 4)
dean.running # 在@property的属性中进行判断
# I am running # @property等三个装饰器
david.country = "America"
print(david.country)
del david.country # 如果这里的不出现_country则这样就可以删除,但是用self.country则真的变成了属性,所以为了区别多定义了一个_country
del david._country # 如今需要再把这个中间变量删除掉才可以
# 无法再调用 david.country # 不用装饰器,用函数的形式
david.city = "Beijing"
print(david.city) # Beijing
Cat
这里定义了Cat类和它的子类Blackcat,主要说明两个主题:私人属性、方法的继承与覆盖
- 私人属性的使用是受到一定限制的,这里主要说明在哪些地方可以用,哪些地方不能调用
- 因为子类继承父类时,会将父类的所有方法都继承过来,但是如果在子类中定义了一个和父类同名的方法,则会将父类的方法覆盖下去,__init__也是如此
定义类
class Cat(Animal): def __init__(self, weight): # 覆盖了父类的__init__,所以定义实例时不需要指定name和age
self.__weight = weight
self._weight = weight + 1
self.weight = self._weight + 1 def get_myweight(self):
print("My weight is", self._weight, "kg") def get_trueweight(self):
print("Actually the cat's weight is",self.__weight) @staticmethod
def print_cat():
print("这个类是Animal类的子类,也是Blackcat类的父类")
print("Cat类和Blackcat类结合,主要用于讲解私人属性、方法的继承与覆盖") print("weight是普通属性,可以在外部访问,即用类调用属性获得,可以被子类内部调用")
print("_weight这样前面加一个下划线表示希望你不要在外部访问它,但是还是可以访问的,可以被子类内部调用")
print("__weight这样加两个下划线的是不允许外部访问的,只可以在类中被调用,不可以被子类内部调用") print("__init__在子类中定义则覆盖了父类中的__init__,不需要指定父类中的属性,也无法调用父类的属性")
print("在子类中实现和父类同名的方法,也会把父类的方法覆盖掉") class Blackcat(Cat): def get_weight(self):
print("My weight is", self.weight) def get_weight_again(self): # 可以
print("Actuall my weight is", self._weight) def get_true_weight(self): # 这个方法因为无法调用self.__weight所以这个方法无法使用
print("My weight is exactly", self.__weight) def get_trueweight(self): # 覆盖了Cat父类中定义的方法
print("My weight is exactly", self._weight+1)
创建实例
# 测试私人变量的外部访问
cole = Cat(5)
cole.weight
#
cole._weight
#
cole.get_trueweight() # 在类中引用__weight,用这个方法返回
# Actually the cat's weight is 5
cole._Cat__weight # 非要访问也可以,其实是python解释器把__weight改成了_Cat__weight
# # 测试私人变量的子类调用
cain = Blackcat(5)
cain.get_weight()
# My weight is 7
cain.get_weight_again()
# Actuall my weight is 6
# cain.get_true_weight() # 报错 # 测试方法的继承与覆盖
cain.get_myweight() #
# My weight is 6 kg
cain.get_trueweight() # 子类中同名函数覆盖父类
# My weight is exactly 7
Tiger
Tiger 和 Whitetiger类中主要讲解super的用法。super用于在子类中调用父类方法及属性。我们上面讲过,子类实例可以直接使用父类的方法,而在子类的定义中,肯定不能直接将父类的方法和属性当成已经定义的而拿过来用,因为那些属性和方法都是父类的,self指向的是父类而不是子类,所以用self调用不了这些方法和属性。所以super就是一个用来创建父类的self以调用父类方法和属性的函数
super(Whitetiger, self) 表示Whitetiger类的父类的self,它就可以调用父类的方法和属性了
创建实例
class Tiger: def __init__(self, name):
self.name = name def eat(self):
return "I am eating" def myname(self):
return "my name is " + self.name class Whitetiger(Tiger): # 继承父类中的属性,再添加
def __init__(self, name, height): # 调用父类中的name也要写在这里
# 注意这里继承属性需要把所有属性全都继承过来
super(Whitetiger, self).__init__(name) # 用super调用函数的参数也都要写全 # Tiger.__init__(self, name) # 也可以这样不用super
# 但是当Whitetiger的代码需要修改,继承的父类改变,这样写就需要改很多地方,所以最好用super self.height = height # 简单调用父类方法
def eatmore(self):
return super(Whitetiger, self).eat() + " more" # 定义这个时要使用父类中的属性name,必须在__init__中将name属性继承过来才能使用这个方法
def realname(self):
return "Actually " + super(Whitetiger, self).myname()
创建实例
wtony = Whitetiger("Tony",100)
wtony.eatmore() # 'I am eating more'
wtony.realname() # 'Actually my name is Tony'
参考
Python入门之面向对象编程(二)python类的详解的更多相关文章
- Python入门之面向对象编程(四)Python描述器详解
本文分为如下部分 引言——用@property批量使用的例子来引出描述器的功能 描述器的基本理论及简单实例 描述器的调用机制 描述器的细节 实例方法.静态方法和类方法的描述器原理 property装饰 ...
- Python进阶之面向对象编程(二)
Python面向对象编程(二) .note-content {font-family: "Helvetica Neue",Arial,"Hiragino Sans GB& ...
- python之路---面向对象编程(二)
类的继承 1.在python3中,只有新式类,新式类的继承方式为:广度优先.而python2中,经典类的继承方式为:深度优先.那么我们来看看深度优先和广度优先的区别吧 如下图,为类之间的继承关系.B, ...
- Python入门之面向对象编程(一)面向对象概念及优点
概念 谈到面向对象,很多程序员会抛出三个词:封装.继承和多态:或者说抽象.一切都是对象之类的话,然而这会让初学者更加疑惑.下面我想通过一个小例子来说明一下 面向对象一般是和面向过程做对比的,下面是一个 ...
- python基础之面向对象编程介绍、类和对象
面向对象变成介绍 面向过程编程 核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西.主要应用在一旦完成很少修改的地方,如linux ...
- Python入门之获取当前所在目录的方法详解
#本文给大家讲解的是使用python获取当前所在目录的方法以及相关示例,非常的清晰简单,有需要的小伙伴可以参考下 sys.path 模块搜索路径的字符串列表.由环境变量PYTHONPATH初始化得到. ...
- Python学习之==>面向对象编程(二)
一.类的特殊成员 我们在Python学习之==>面向对象编程(一)中已经介绍过了构造方法和析构方法,构造方法是在实例化时自动执行的方法,而析构方法是在实例被销毁的时候被执行,Python类成员中 ...
- Python:面向对象编程3 定制类(有更新)
Python:面向对象编程3 定制类(有更新) ⚠️本文主要内容为对Data model相关知识点的提取学习记录.(内容来自文档和部分网页教程案例) ⚠️:这个连接指向<流畅的python&g ...
- Python入门篇-面向对象概述
Python入门篇-面向对象概述 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.语言的分类 面向机器 抽象成机器指令,机器容易理解 代表:汇编语言 面向过程 做一件事情,排出个 ...
随机推荐
- postgresql----数组类型和函数
postgresql支持数组类型,可以是基本类型,也可以是用户自定义的类型.日常中使用数组类型的机会不多,但还是可以了解一下.不像C或JAVA高级语言的数组下标从0开始,postgresql数组下标从 ...
- 初学filter
一. Filter介绍 Filter可以认为是Servlet的一种加强版,它主要用于对用户请求进行预处理,也可以对HTTPServletResponse进行后处理,是个典型的处理链.它的完整处理流程是 ...
- TFS二次开发11——标签(Label)
下图是在VS2010里创建Label的界面 可以看出创建Label 需要如下参数:Name.Comment.Path.Version .下面是代码实现: using Microsoft.TeamFou ...
- PPTP不使用远程网关访问公网设置
使用PPTP拨号的时候默认使用PPTP远程网关访问公网,通过以下设置可以禁止远程网关访问公网 1,右下角选择网络图标右键-属性 2,选择网络IPv4属性,选择属性 3,点击高级选项 4,在远程网络上使 ...
- Oracle to_date()函数的用法介绍
to_date()是Oracle数据库函数的代表函数之一,下文对Oracle to_date()函数的几种用法作了详细的介绍说明,需要的朋友可以参考下 在Oracle数据库中,Oracle t ...
- Gym - 101028I March Rain 二分
http://codeforces.com/gym/101028/problem/I 题意:给你n个洞,k个布条,问布条能贴到所有洞时的最小值. 题解:二分答案,因为答案越大就越容易满足条件. 技巧: ...
- ArcGIS API for javascript开发笔记(五)——GP服务调用之GP模型的发布及使用详解
感谢一路走来默默陪伴和支持的你~~~ ----------------欢迎来访,拒绝转载---------------- 关于GP模型的制作请点我! 一.GP发布 ArcGIS Desktop可以作为 ...
- python xlwt 设置单元格样式-合并单元格
xlwt模块详解--合并单元格 import xlwtworkbook = xlwt.Workbook()worksheet = workbook.add_sheet('My sheet')# 合并第 ...
- Heavy Transportation---poj1797
求(Dijkstra算法,求每条路径上的最小值 的最大值)和青蛙的那题类似: #include<iostream> #include<stdio.h> #include&l ...
- mysql 数据操作 多表查询 目录
mysql 数据操作 多表查询 准备 多表连接查询介绍 mysql 数据操作 多表查询 多表连接查询 笛卡尔积 mysql 数据操作 多表查询 多表连接查询 内连接 mysql 数据操作 多表查询 多 ...