300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > Python 类—类属性(私有属性 公有属性 实例属性 局部变量)类方法(实例方法 静态方法)

Python 类—类属性(私有属性 公有属性 实例属性 局部变量)类方法(实例方法 静态方法)

时间:2020-08-04 08:38:40

相关推荐

Python 类—类属性(私有属性 公有属性 实例属性 局部变量)类方法(实例方法 静态方法)

1. 创建类

类是对某个对象的定义,它包含有关对象动作方式的信息,包括它的名称、方法、属性和事件。类不存在于内存中,因此它本身并不是对象。当程序运行需要引用类的代码时,就会在内存中创建一个类的新实例,即对象。虽然只有一个类,但能以这个类在内存中创建多个相同类型的对象。

class Person(object):#类的方法中必须要有一个self参数,但是方法被调用时,不用传递这个参数def get_name(self):print "my name is: lili"def get_age(self):print "my age is : 20"def get_hoppy(self):print "My hoppy is :lvyou"boy = Person()boy.get_name() #但是方法被调用时,不用传递这个参数boy.get_age() #在调用get_age等方法时,boy自动将自己作为一个参数传入方法中,因此我们称它为selfboy.get_hoppy()

使用 PyCharm 进行 Python 开发时,在类中定义方法时,若该方法不涉及对属性的操作,那么PyCharm 会提示 Method xxx may be ‘static’,因为 PyCharm 会认为该方法是一个静态方法,而不是类方法,所提提示我们在该方法前添加 @staticmethod 装饰器进行装饰。

2. 类的封装和多态

所谓封装,即将抽象得到的数据和行为(功能)相结合,形成一个有机整体,也就是将数据和操作数据的源代码进行有机整合,形成类。

其中数据和函数都是类的成员。目的是隐藏对象的属性和实现细节,对外公开接口,在程序中控制属性的读和修改的访问级别。

封装和多态的区别:多态可以让用户对不知道是什么类的对象进行方法调用,而封装则不用关心对象是如何创建的而直接进行使用。

class MyClass(object):# 定义一个全局变量name = 'xml'def set_name(self, name):self.name = namedef get_name(self):return self.namemy = MyClass()my.set_name('Jack')print my.get_name()# 如果将变量存储到全局变量name中时,实例化MyClass之后,全局变量name将会改变my = MyClass()my.name = 'Tom'print my.get_name()# 对象有自己的状态,对象的状态由它的特性名称来描述,eg:下面she对象的内容不影响my对象的内容she = MyClass()she.set_name('angel')print she.get_name()print my.get_name()

3. 类的属性

私有属性

函数、方法或者属性的名称以两个下划线开始,则为私有类型;

公有属性

如果函数、方法或者属性的名称没有以两个下划线开始,则为公有属性;

实例属性

以self作为前缀的属性;

局部变量

类的方法中定义的变量没有使用self作为前缀声明,则该变量为局部变量;

以单下划线开头(_foo)的代表不能直接访问的类属性,需通过类提供的接口进行访问,不能用from xxx import导入;

以双下划线开头的(__foo)代表类的私有成员;

以双下划线开头和结尾的(__ foo__)代表Python里特殊方法专用的标识,如__init()__代表类的构造函数。

class Fly():price = 123 #公有的类属性def __init__(self):self.direction = "beijing" #公有的实例属性 self.__city = '陕西'#私有的实例属性isPeople = "more people"#局部变量if __name__ == '__main__':print Fly.price#print Fly.direction 公有的实例属性在未实例化之前不能使用,该语句是错误的traveller = Fly()print traveller.direction#print traveller.__city Fly instance has no attribute '__city'print traveller._Fly__city #私有属性的访问方式:实例化对象名._类名__私有属性名#print traveller.isPeople 局部变量不能被实例化对象traveller所引用Fly.price = traveller.price + 10print "the Fly prise is " + str(Fly.price)mytraveller = Fly()print "I think the price is " + str(mytraveller.price)

数据属性不需要预先定义,数据属性初次被使用时,即被创建并赋值。

class Data_attribute():passif __name__ == "__main__":data = Data_attribute()data.name = "我是没有被预先定义的数据"print data.name

类数据属性属于类本身,可以通过类名进行访问/修改类数据属性也可以被类的所有实例访问 / 修改在类定义之后,可以通过类名动态添加类数据属性,新增的类属性也被类和所有实例共有实例数据属性只能通过实例访问在实例生成后,还可以动态添加实例数据属性,但是这些实例数据属性只属于该实例

class Student(object):count = 0books = []'''"count" "books" "name"和"age"都被称为类的数据属性,但是它们又分为类数据属性和实例数据属性'''def __init__(self, name, age):# 类的初始化函数"__init__"self.name = nameself.age = agepass# 1、类数据属性Student.books.extend(['python', 'javascript'])print 'Student book list: %s' % Student.books# Student book list: ['python', 'javascript']# class can add class attribute after class defineStudent.hobbies = ['reading', 'jogging', 'swimming']print 'Student hobbies list: %s' % Student.hobbies# Student hobbies list: ['reading', 'jogging', 'swimming']print dir(Student)'''['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'books', 'count', 'hobbies']'''# 2、实例数据属性wilber = Student('wilber', 28)print '%s is %d years old' % (wilber.name, wilber.age)# wilber is 28 years old# class instance can add new attribute# "gender" is the instance attribute only belongs to wilberwilber.gender = 'male'print '%s is %s' % (wilber.name, wilber.gender)# class instance can access class attributeprint dir(wilber)wilber.books.append('C#')print wilber.bookswill = Student("Will", 27)print "%s is %d years old" % (will.name, will.age)# will shares the same class attribute with wilber# will don't have the "gender" attribute that belongs to wilberprint dir(will)print will.books

4. 类的方法

类方法

类方法使用 @classmethod 指令来声明;

类实例方法

实例方法则无需使用指令来说明;实例方法的第一个参数必须是"self",实例方法只能通过类实例进行调用,这时候"self"就代表这个类实例本身。通过"self"可以直接访问实例的属性

与实例方法和类方法不同,静态方法没有参数限制,既不需要实例参数,也不需要类参数,定义的时候使用 @staticmethod 装饰器。

同类方法一样,静态法可以通过类名访问,也可以通过实例访问。

这三种方法的主要区别在于参数,实例方法被绑定到一个实例,只能通过实例进行调用;但是对于静态方法和类方法,可以通过类名和实例两种方式进行调用。

class MyClass():def __init__(self):passdef aa(self, message): # 类实例方法print "执行实例方法 aa(%s,%s)" %(self,message)@classmethoddef class_method(cls, message): # 类方法print "执行类方法 class_method(%s,%s)" %(cls,message)@staticmethoddef static_method(): # 类静态方法print "我是被定义的静态方法"if __name__ == "__main__":qq = MyClass()qq.aa('hello')# My_object.aa('hello') 类实例方法aa只能被类实例调用,不能被类调用# 类方法和静态方法可以直接被类和类实例调用qq.class_method('hello')MyClass.class_method('hello')qq.static_method()MyClass.static_method()

为什么要用到静态方法呢? 如下示例说明:

静态方法用到的场景就是和类相关的操作,但是又不会依赖和改变类、实例的状态,比如经常有跟类有关系的函数,我们希望它在运行时又不需要实例和类参与的情况下直接就能调用。调用静态方法可以无需创建对象。

class Robot(object):def __init__(self, data):self.data = data@staticmethoddef is_need():return Truedef reboot(self):if Robot.is_need():# 调用类中的静态方法print "The pc will reboot for {0}".format(self.data)def restore(self):if Robot.is_need():print "The pc will restort for {0}".format(self.data)robot1 = Robot("cmd")robot1.reboot()robot1.reboot()

类方法的示例

In [15]: class Student(object):...: num_student=0...: def __init__(self):...: Student.num_student+=1...: ...: @classmethod...: def get_num_of_instance(cls):...: return cls.num_student...: In [16]: s1=Student()In [17]: s1.get_num_of_instance()Out[17]: 1In [18]: s2=Student()In [19]: s2.get_num_of_instance()Out[19]: 2In [20]: Student.get_num_of_instance()Out[20]: 2In [21]: s3=Student()In [22]: Student.get_num_of_instance()Out[22]: 3

简单记录一下 classmethod 和 staticmethod 的区别:

classmethod 是类方法,而 staticmethod 是静态方法。

在 Python中,静态方法和类方法都是可以通过类对象和类对象实例访问。但是区别是:

@classmethod 是一个函数修饰符,它表示接下来的是一个类方法,类方法的第一个参数 cls,而实例方法的第一个参数是 self,表示该类的一个实例。

普通对象方法至少需要一个 self 参数,代表类对象实例,类方法有类变量 cls 传入,从而可以用 cls 做一些相关的处理。并且有子类继承时,调用该类方法时,传入的类变量 cls 是子类,而非父类。

对于类方法,可以通过类来调用,比如说 A 是一个类,那么我们可以通过 A.method() 来调用 A 里面的 method 方法, 也可以通过类的一个实例来调用,如 A().method() 进行调用,首先 A() 方法会调用 A 的初始化方法进行实例化出一个 A 的对象,然后通过该对象调用 method 方法。

静态方法则没有上述方法,它基本上跟一个全局函数相同,一般来说用的很少。

5. 类的继承

继承是指一个对象直接使用另一个对象的属性和方法,当一个类拥有另一个类的所有数据和操作时,就称这两个类之间具有继承关系,被继承的类称为父类或者超类,继承了父类或者超类的所有数据和操作的类称为子类。

继承类语法:

class class_name(fatherclass_name)

fatherclass_name代表的是class_name要继承的类 。

如何调用父类的方法:使用类名访问父类中的方法,并在参数列表中引入对象 self。

class Father():def __init__(self):print '我是初始化Father类中的方法'print '供以后调用'class Son(Father):def __init__(self):print '我是初始化Son类中的方法'Father.__init__(self) # 使用类名访问父类中的方法,并在参数列表中引入对象selfchild = Son()

下面看一个例子,我们以学校的老师和学生为例,老师和学生有共同的特征:姓名、年龄、地址、喜好,不同的是老师有工资,学生有成绩。

我们将学校成员归为一个共同的类。

class SchoolMember(object):def __init__(self, name, age, addr, hoppy):self.name = nameself.age = ageself.addr = addrself.hoppy = hoppyprint '初始化的名字是%s' %self.namedef tell(self):print '姓名:%s,年龄:%s,地址:%s,喜好:%s' %(self.name,self.age,self.addr,self.hoppy)

Teacher 类继承 SchoolMember 类,采用新式类继承写法时,super() 会带两个参数,第一个是子类的类名,第二个是 self 参数。super() 可以避免一些类继承的潜在问题,特别是在多重继承上。

class Teacher(SchoolMember):def __init__(self, name, age, addr, hoppy, salary):# 使用类名访问父类中的方法,并在参数列表中引入对象selfSchoolMember.__init__(self, name, age, addr, hoppy) # 新式类继承写法# super(Teacher, self).__init__(name, age, addr, hoppy)self.salary = salary # 添加salary属性print '我是继承SchoolMember的老师%s' %(self.name)def tell(self):SchoolMember.tell(self)print '我这次的工资是 %s' %self.salary

Student 类继承 SchoolMember 类

class Student(SchoolMember):def __init__(self, name, age, addr, hoppy, marks):SchoolMember.__init__(self, name, age, addr, hoppy)self.marks = marks# 添加marks属性print '我是继承SchoolMember的学生%s' %(self.name)def tell(self):SchoolMember.tell(self)print '我这次的成绩是 %s' %self.marks# 分别创建Teacher和Student的实例t = Teacher('Tom', 40, '陕西西安', '篮球',3000)s = Student('jack', 14, '北京', '足球', 90)members = (t, s)for member in members:member.tell()'''程序输出结果如下:我是初始化Son类中的方法我是初始化Father类中的方法供以后调用初始化的名字是Tom我是继承SchoolMember的老师Tom初始化的名字是jick我是继承SchoolMember的学生jick姓名:Tom,年龄:40,地址:陕西西安,喜好:篮球我这次的工资是 3000姓名:jack,年龄:14,地址:北京,喜好:足球我这次的成绩是 90'''

6. 类的多重继承

子类继承多个父类的方法:

class class_name(fatherclass_name,fatherclass_name1,......):

其中,class_name为类名,fatherclass_name,fatherclass_name1 为父类名。

class MyFather():def __init__(self):self.eye = '爸爸的眼睛是双眼皮'print self.eyeclass MyMother():def __init__(self):self.forehead = '妈妈的额头有点宽'print self.foreheadclass MyAunt():def __init__(self):self.nose = '姑姑的鼻子是高鼻梁'print self.noseclass MySelf(MyFather, MyMother, MyAunt):def __init__(self, face):print '我的眼睛是双眼皮,别人说我是继承的是:'MyFather.__init__(self)print '我的额头有点宽,别人说我是继承的是:'MyMother.__init__(self)print '我的鼻子有点宽,别人说我是继承的是:'MyAunt.__init__(self)self.face = faceprint '我的脸型:%s' %self.face,'这下终于没人说我像谁了'me = MySelf('偏圆吧')

7. 通过对象修改类属性

通过对象可以修改类属性值。但这是危险的。类属性被所有同一类及其子类的对象共享。类属性值的改变会影响所有的对象。

class Human(object):Age = 0Name = ["Li", "Lei"]a = Human()b = Human()a.Age += 1print a.Ageprint b.Age# b.Age不会改变 Age是immutable型a.Name[0] = "Wang"print a.Nameprint b.Name # b.Name会改变Name是mutable型'''程序输出结果如下:10['Wang', 'Lei']['Wang', 'Lei']'''

为什么immutable变量是可行的呢?原因是,在更改对象属性时,如果属性是immutable的,该属性会被复制出一个副本,存放在对象的__dict__中。你可以通过下面的方式查看:

print a.__class__.__dict__print a.__dict__

注意到类中和对象中各有一个Age。一个为0, 一个为1。所以我们在查找a.Age的时候,会先查到对象的__dict__的值,也就是1。

但mutable的类属性,在更改属性值时,并不会有新的副本。所以更改会被所有的对象看到。

8. 类中的方法调用其它方法

class Human(object):laugh = 'hahahahaha'def show_laugh(self):print self.laughdef laugh_10th(self):for i in range(10):self.show_laugh()li_lei = Human()li_lei.laugh_100th()#类属性laugh ,在方法show_laugh()中,通过self.laugh,调用了该属性的值。#还可以用相同的方式调用其它方法。方法show_laugh(),在方法laugh_100th中()被调用

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。