python定义circle类_Python笔记——类与对象

面向对象的程序设计具有封装、继承、多态3个基本特征,可以大大增加程序可靠性、代码可重用行和程序可维护性,从而提高程序的开发效率。

类对象与实例对象

类对象

# 类对象

class 类名:

类体

class Person1:

pass

# 测试代码

p1 = Person1()

print(Person1, type(Person1), id(Person1))

print(p1, type(p1), id(p1))

实例对象

# 实例对象

anObject = 类名(参数列表)

anObject.对象函数 或 anObject.对象属性

Python创建实例对象的方法无需使用关键字new,而是直接调用类对象并传递参数。因此,类对象是可调用对象。

Python内置函数中,可调用内置类对象bool / int / str / list / dict / set

# 实例对象的创建实例

c1 = complex(1, 2)

c1.conjugate()

c1.real

# output

(1-2j)

1.0

属性

Python变量不需要声明,可直接使用。

实例对象属性

通过“self.变量名”定义的属性称为实例对象属性,也称为实例对象变量。类的每个实例都包含了该类的实例对象变量的一个单独副本,实例对象变量属于特定的实例。实例对象变量在类的内部通过self访问,在外部通过对象实例访问。

# 实例对象属性一般在__init__()方法中初始化

self.实例变量名 = 初始值

# 在其他实例函数中通过self访问

self.实例变量名 = 值

# 创建对象实例后通过对象实例访问

obj1 = 类名()

obj1.实例变量名 = 值

obj1.实例变量名

class Person2:

def __init__(self, name, age): # 初始化__init__()方法

self.name = name

self.age = age

def say_hi(self):

print('您好,我叫', self.name)

# 测试代码

p1 = Person2('张三', 25)

p1.say_hi()

print(p1.age)

类对象属性

class Person3:

count = 0

name = "Person"

类属性如果通过obj.属性名来访问,则属于实例的实例属性。虽然类属性可以使用对象实例来访问,但容易造成困惑,访问类属性建议使用标准的访问方式"类名.变量名"

私有属性和共有属性

Python类的成员没有范文控制限制。

# 私有属性:以两下划线开头,但不以两下划线结束

class A:

__name = 'class A'

def get_name():

print(A.__name)

A.get_name()

A.__name # 不可访问私有类属性

@property装饰器

面向对象编程的封装性原则要求不直接访问类中的数据成员。在Python中可以定义私有属性,然后定义相应的访问该私有属性的函数,并使用@property装饰器来装饰这些函数。程序可以把函数“当作”属性访问,从而提供更加友好的访问方式。

class Person11:

def __init__(self, name):

self.__name = name

@property

def name(self):

return self.__name

# 测试代码

p = Person11('Estellasy')

print(p.name)

class Person12:

def __init__(self, name):

self.__name = name

@property

def name(self):

return self.__name

@name.setter

def name(self, value):

self.__name = value

@name.deleter

def name(self):

del self.__name

#测试代码

p = Person12('姚六')

p.name = '王依依'

print(p.name)

# property的调用格式如下

property(fget=None, fset=None, fdel=None, doc=None)

# 其中,fget为get访问器;fset为set访问器;fdel为del访问器

特殊属性

以双下划线开始和结束的属性

自定义属性

@Override

方法

对象实例方法

在一般情况下,类方法的第一个参数一般为self,这种方法称为对象实例方法。

def 方法名(self, [形参列表]):

函数体

对象.方法名([实参列表])

class Person4: #定义类Person4

def say_hi(self, name): #定义方法say_hi

self.name = name #把参数name赋值给self.name,即成员变量name(域)

print('您好, 我叫', self.name)

p4 = Person4() #创建对象实例

p4.say_hi('Alice') #调用对象实例的方法

静态方法

与类的对象实例无关的方法,称之为静态方法。

静态方法不对特定实例进行操作,在静态方法中访问对象实例会导致错误。静态方法通过装饰器@staticmethod来定义,其声明格式如下。

@staticmetho

def 静态方法名([形参列表]):

函数体

一般通过类名来访问,也可以通过对象实例来调用。

class TemperatureConverter:

@staticmethod

def c2f(t_c): #摄氏温度到华氏温度的转换

t_c = float(t_c)

t_f = (t_c * 9/5) + 32

return t_f

@staticmethod

def f2c(t_f): #华氏温度到摄氏温度的转换

t_f = float(t_f)

t_c = (t_f - 32) * 5 /9

return t_c

#测试代码

print("1. 从摄氏温度到华氏温度.")

print("2. 从华氏温度到摄氏温度.")

choice = int(input("请选择转换方向:"))

if choice == 1:

t_c = float(input("请输入摄氏温度: "))

t_f = TemperatureConverter.c2f(t_c)

print("华氏温度为: {0:.2f}".format(t_f))

elif choice == 2:

t_f = float(input("请输入华氏温度: "))

t_c = TemperatureConverter.f2c(t_f)

print("摄氏温度为: {0:.2f}".format(t_c))

else:

print("无此选项,只能选择1或2!")

类方法

Python也允许声明属于类本身的方法,即类方法。类方法不对特定实例进行操作,在类方法中访问对象实例属性会导致错误。类方法通过装饰器@classmethod来定义,第一个形式参数必须为类对象本身,通常为cls。

@classmethod

def 类方法名(cls, [形参列表]):

函数体

# 类方法一般通过类名来访问,也可以通过对象实例来调用。

类名.类方法名([实参列表])

class Foo:

classname = "Foo"

def __init__(delf, name):

self.name = name

def f1(self):

print(self.name)

@staticmethod

def f2():

print("static")

@classmethod

def f3():

print(cls.classname)

#测试代码

f = Foo("李")

f.f1()

Foo.f2()

Foo.f3()

在Python类体中可以定义特殊的方法,例如__new__()方法和__init__()方法。

__new__()方法是一个类方法,在创建对象时调用,返回当前对象的一个实例,一般无须重载该方法。

__init__()方法即构造函数(构造方法),用于执行类的实例的初始化工作。在创建完对象后调用,初始化当前对象的实例,无返回值。

class Person5: #定义类Person5

def __init__(self, name): #__init__方法

self.name = name #把参数name赋值给self.name,即成员变量name(域)

def say_hi(self): #定义类Person的方法say_hi

print('您好, 我叫', self.name)

p5 = Person5('Helen') #创建对象

p5.say_hi() #调用对象的方法

__del__方法即析构函数(析构方法),用于实现销毁类的实例所需的操作,如释放对象占用的非托管资源(例如:打开的文件、网络连接等)

默认情况下,当对象不再被使用时,__del__方法运行,由于Python解释器实现自动垃圾回收,即无法保证这个方法究竟在什么时候运行

通过del语句,可以强制销毁一个对象实例,从而保证调用对象实例的__del__方法。

class Person3:

count = 0 #定义类域count,表示计数

def __init__(self, name,age): #构造函数

self.name = name #把参数name赋值给self.name,即成员变量name(域)

self.age = age #把参数age赋值给self.age,即成员变量age(域)

Person3.count += 1 #创建一个实例时,计数加1

def __del__(self): #析构函数

Person3.count -= 1 #销毁一个实例时,计数减1

def say_hi(self): #定义类Person3的方法say_hi()

print('您好, 我叫', self.name)

def get_count(): #定义类Person3的方法get_count()

print('总计数为:', Person3.count)

print('总计数为:',Person3.count) #类名访问

p31 = Person3('张三',25) #创建对象

p31.say_hi() #调用对象的方法

Person3.get_count() #通过类名访问

p32 = Person3('李四',28) #创建对象

p32.say_hi() #调用对象的方法

Person3.get_count() #通过类名访问

del p31 #删除对象p31

Person3.get_count() #通过类名访问

del p32 #删除对象p32

Person3.get_count() #通过类名访问

两个下划线开头,但不以两个下划线结束的方法是私有的(private),其他为公共的(public).

以双下划线开始和结束的方法是Python的专有特殊方法。不能直接访问私有方法,但可以在其他方法中访问

class Book: #定义类Book

def __init__(self, name, author, price):

self.name = name #把参数name赋值给self.name,即成员变量name(域)

self.author = author#把参数author赋值给self.author,即成员变量author(域)

self.price = price #把参数price赋值给self.price,即成员变量price(域)

def __check_name(self): #定义私有方法,判断name是否为空

if self.name == '' : return False

else: return True

def get_name(self): #定义类Book的方法get_name

if self.__check_name():print(self.name,self.author) #调用私有方法

else:print('No value')

b = Book('Python程序设计教程','江红',59.0) #创建对象

b.get_name() #调用对象的方法

b.__check_name() #直接调用私有方法,非法

方法重载

可以定义多个重名的方法,只要保证方法签名是唯一的

方法签名包括三个部分:方法名、参数数量和参数类型

class Person21:

def say_hi(self, name = None):

self.name = name

if name == None:

print('您好')

else:

print('您好,我叫', self.name)

p21 = Person21()

p21.say_hi()

p21.say_hi('任思怡')

class Person22: #定义类Person22

def say_hi(self, name): #定义类方法say_hi,带两个参数

print('您好, 我叫', self.name)

def say_hi(self, name, age): #定义类方法say_hi,带三个参数

print('hi, {0}, 年龄:{1}'.format(name,age))

p22 = Person22() #创建对象

p22.say_hi('Lisa', 22) #调用对象的方法

#p22.say_hi('Bob') #TypeError: say_hi() missing 1 required positional argument: 'age'

Python类体中定义多个重名的方法虽然不会报错,但只有最后一个方法有效,所以建议不要定义重名的方法。

继承

派生类:python支持多重继承,即一个派生可以继承多个基类

声明派生类时,必须在其构造函数中调用基类的构造函数

class Person: #基类

def __init__(self, name, age): #构造函数

self.name = name #姓名

self.age = age #年龄

def say_hi(self): #定义基类方法say_hi

print('您好, 我叫{0}, {1}岁'.format(self.name,self.age))

class Student(Person): #派生类

def __init__(self, name, age, stu_id): #构造函数

Person.__init__(self, name, age) #调用基类构造函数

self.stu_id = stu_id #学号

def say_hi(self): #定义派生类方法say_hi

Person.say_hi(self) #调用基类方法say_hi

print('我是学生, 我的学号为:', self.stu_id)

p1 = Person('张王一', 33) #创建对象

p1.say_hi()

s1 = Student('李姚二', 20, '2018101001') #创建对象

s1.say_hi()

查看继承的层次关系

通过类的方法mro()或类的属性__mro__可以输出其继承的层次关系

class A: pass

class B(A): pass

class C(B): pass

class D(A): pass

class E(B, D): pass

D.mro()

E.__mro__

类成员的继承和重写

通过继承,派生类继承基类中除构造方法之外的所有成员

如果在派生类中重新定义从基类继承的方法,则派生类中定义的方法覆盖从基类中继承的方法

class Dimension: #定义类Dimensions

def __init__(self, x, y): #构造函数

self.x = x #x坐标

self.y = y #y坐标

def area(self): #基类的方法area()

pass

class Circle(Dimension): #定义类Circle(圆)

def __init__(self, r): #构造函数

Dimension.__init__(self, r, 0)

def area(self): #覆盖基类的方法area()

return 3.14 * self.x * self.x #计算圆面积

class Rectangle(Dimension): #定义类Rectangle(矩形)

def __init__(self, w, h): #构造函数

Dimension.__init__(self, w, h)

def area(self): #覆盖基类的方法area()

return self.x * self.y #计算矩形面积

d1 = Circle(2.0) #创建对象:圆

d2 = Rectangle(2.0, 4.0) #创建对象:矩形

print(d1.area(), d2.area()) #计算并打印圆和矩形面积

Python面向对象程序设计 续

对象的特殊方法

包含许多以双下划线开始和结束的方法

创建对象实例时,自动调用__init__方法,a

fef085aedd5a

class Person:

def __init__(self, name, age): #特殊方法(构造函数)

self.name = name

self.age = age

def __str__(self): #特殊方法,输出成员变量

return '{0}, {1}'.format(self.name,self.age)

#测试代码

p1 = Person('张三', 23)

print(p1)

运算符重载与对象的特殊方法

Python的运算符实际上是通过调用对象的特殊方法实现的

fef085aedd5a

# 运算符重载示例

class MyList: #定义类MyList

def __init__(self, *args): #构造函数

self.__mylist = [] #初始化私有属性,空列表

for arg in args:

self.__mylist.append(arg)

def __add__(self, n): #重载运算符"+",每个元素增加n

for i in range(0, len(self.__mylist)):

self.__mylist[i] += n

def __sub__(self, n): #重载运算符"-",每个元素减少n

for i in range(0, len(self.__mylist)):

self.__mylist[i] -= n

def __mul__(self, n): #重载运算符"*",每个元素乘以n

for i in range(0, len(self.__mylist)):

self.__mylist[i] *= n

def __truediv__(self, n): #重载运算符"/",每个元素除以n

for i in range(0, len(self.__mylist)):

self.__mylist[i] /= n

def __len__(self): #对应于内置函数len(),返回列表长度

return(len(self.__mylist))

def __repr__(self): #对应于内置函数str(),显示列表

str1 = ''

for i in range(0, len(self.__mylist)):

str1 += str(self.__mylist[i]) + ' '

return str1

#测试代码

m = MyList(1, 2, 3, 4, 5) #创建对象

m + 2; print(repr(m)) #每个元素加2

m - 1; print(repr(m)) #每个元素减1

m * 4; print(repr(m)) #每个元素乘4

m / 2; print(repr(m)) #每个元素除2

print(len(m)) #列表长度

@functools.total ordering装饰器

支持大小比较的对象需要实现特殊方法:__eq__、__lt__、__le__、__ge__、__gt__

使用functools模块的total_ordering装饰器装饰类,则只需要实现__eq__,以及__lt__、__le__、__ge__、__gt__中的任意一个

total_ordering装饰器实现其他比较运算,以简化代码量

import functools

@functools.total_ordering

class Student:

def __init__(self, firstname, secondname):

self.firstname = firstname

self.secondname = secondname

def __eq__(self, other): #判断姓名是否一致

return ((self.lastname.lower(), self.firstname.lower()) == (other.lastname.lower(), other.firstname.lower()))

def __lt__(self, other): #self姓名

return ((self.lastname.lower(), self.firstname.lower()) < (other.lastname.lower(), other.firstname.lower()))

#测试代码

if __name__ == '__main__':

s1 = Student('Mary','Clinton')

s2 = Student('Mary','Clinton')

s3 = Student('Charlie','Clinton')

print(s1==s2)

print(s1>s3)

__call__方法和可调用对象(callabe)

Python类体中可以定义一个特殊的方法:__call__方法

定义了__call__方法的对象称之为可调用对象

class GDistance:

def __init__(self, g):

self.g = g

def __call__(self, t):

return (self.g*t**2)/2

# 测试代码

if __name__ = '__main__':

e_gdist = GDistance(9.8)

for t in range(11):

print(format(e_gdist(t), "0.2f"),end=' ')

对象的引用、浅拷贝和深拷贝

对象的引用:对象的赋值,id相同

对象的浅拷贝:对象的赋值会引用同一个对象,即不拷贝对象

切片操作

对象实例化

copy函数

import copy

acc1 = ['Charlie', ['credit', 0.0]]

acc2 = acc1[:] # 使用切片方式拷贝对象

acc3 = list(ac1) # 使用对象实例化方法拷贝对象

acc4 = copy.copy(acc1) # 使用copy.copy函数拷贝对象

acc2[0] = 'Mary'

acc2[1][1] = -99.9

对象的深拷贝:如果要递归复制对象中包含的子对象,可以使用copy模块的deepcopy()函数

import copy

acc1 = ['Charlie', ['credit', 0.0]]

acc5 = copy.deepcopy(acc1)

acc5[0] = 'Clinton'

acc5[1][1] = -19.9

可迭代对象:迭代器和生成其

可循环迭代的对象称之为可迭代对象,迭代器和生成器函数是可迭代对象。

相对于序列,可迭代序列仅在迭代时产生数据,故可节省内存空间。

Python语言提供了若干内置可迭代对象:range\map\filter\enumerate\zip

标准库itertools模块中包含各种迭代器。

可迭代对象:实现了__iter__()的对象是可迭代对象

collections.abc模块中定义了抽象基类Iterable,使用内置的isinstance,可以判断一个对象是否为可迭代对象。

import collections.abc

isinstance((1, 2, 3), collections.abc.Iterable)

isinstance('python33',collections.abc.Iterable)

isinstance(123,collections.abc.Iterable)

系列对象都是可迭代对象,生成器函数和生成器表达式也是可迭代对象。

迭代器:实现了__next__()的对象是迭代器

可以使用内置函数next(), 调用迭代器的__next__方法,一次返回下一个项目值

使用迭代器可以实现对象的迭代循环,迭代器让程序更加通用、优雅、高校,更加python化。

import collections.abc

i1 = (i**2 for i in range(10))

insinstance(i1, collections.abc.Iterator)

迭代器对象必须实现两个方法:__iter__()和__next()__,二者合称为迭代器协议。__iter__()用于返回对象本身,以方便for语句进行迭代,__next()__用于返回下一元素

自定义可迭代对象和迭代器

class Fib:

def __init__(self):

self.a, self.b = 0, 1

def __next__(self):

self.a, self.b = self.b, self.a + self.b

return self.a

def __iter__(self):

return self

# 测试代码

fibs = Fib()

for f in fibs:

if f < 1000: print(f, end = ',')

else: break

生成器函数

生成器函数使用yield语句返回一个值,然后保存当前函数整个执行状态,等待下一次调用。

生成器函数是一个迭代器,是可迭代对象,支持迭代

def gentripls(n):

for i in range(n):

yield i*3

f = gentripls(10)

反向迭代 reversed迭代器

使用内置函数reversed(),可以实现一个系列的反向系列

如果一个可迭代对象实现了__reversed__()方法,则可以使用reversed()函数获得其反向迭代对象

生成器表达式

生成器表达式的语法和列表解析基本一样,只不过生成器表达式使用()代替[]

fef085aedd5a

表达式expr使用每次迭代内容iter_var,计算生成一个列表。如果指定了条件表达式cond_expr,则只有满足条件的iterable元素参与迭代

range可迭代对象

迭代时产生指定范围的数字序列,可以节省内存空间

map迭代器和itertool.starmap迭代器

map是可迭代对象,使用指定函数处理可迭代对象的每个元素(如果函数需要多个参数,则对应各可迭代对象),返回结果可迭代对象

filter迭代器和itertools.filterfalse迭代器

filter是可迭代对象,使用指定函数处理可迭代对象的每个元素,函数返回bool类型的值。若结果为True,则返回该元素。如果function为None,则返回元素为True的元素

>>> filter

>>> list(filter(lambda x: x>0, (-1, 2, -3, 0, 5)))

[2, 5]

>>> list(filter(None, (1, 2, 3, 0, 5)))

[1, 2, 3, 5]

如果需要返回结果为False的元素,则需要使用itertools.filterfalse迭代器

filterfalse根据条件函数predicate处理可迭代对象的每个元素,若结果为True,则丢弃;否则返回该元素

>>> import itertools

>>> list(itertools.filterfalse(lambda x: x%2, range(10)))

[0, 2, 4, 6, 8]

zip迭代器和itertools.zip_longest迭代器

zip是可迭代对象,拼接多个可迭代对象iter1、iter2…的元素,返回新的可迭代对象,其元素为各系列iter1、iter2…对象元素组成的元组。如果各系列iter1、iter2…的长度不一致,则截断至最小系列长度。可以节省内存空间

>>> zip #

>>> zip((1,2,3),'abc', range(3)) #

>>> list(zip((1,2,3),'abc', range(3))) #[(1, 'a', 0), (2, 'b', 1), (3, 'c', 2)]

>>> list(zip('abc', range(10))) #[('a', 0), ('b', 1), ('c', 2)]

多个可迭代对象的元素个数不一致时,如果需要取最大的长度,则需要使用itertools. zip_longest迭代器

>>> import itertools

>>> list(itertools.zip_longest('ABCD', 'xy', fillvalue='-'))

[('A', 'x'), ('B', 'y'), ('C', '-'), ('D', '-')]

enumerate迭代器

enumerate是可迭代对象,用于枚举可迭代对象iterable中的元素,返回元素为元组(计数, 元素)的可迭代对象

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值