类的对象
有三种对象 |
可以做什么操作 |
包括什么属性 |
类对象 |
属性引用、实例化 |
函数方法、内置的属性、类变量 |
实例对象 |
属性引用 |
函数方法、类变量、实例变量 |
方法对象 |
1. 类对象、实例对象、方法对象
类[class]是抽象的模型
实例[instance]是根据类创建出来的一个个具体的“对象”
1.1 如何定义类
class 类名(表示该类是从哪个类继承下来的):
xxx
class ClassName:
<statement-1>
.
.
.
<statement-N>
1.2 属性引用
class Myclass(object): '''A simple example about class''' i=123 def f(self): return "hello world" def __init__(self,name,score): self.name=name self.score=score # 引用类变量、方法,都是合理的属性引用,分别返回一个整数和一个函数对象 print(Myclass.i) 123 print(Myclass.f) ->这就叫做创建了方法对象,但要注意这只是创建了对象但不是调用了这个方法 <function Student.f at 0x7f81f42c58c8> # 类还有内置的属性可以被引用 print(Myclass.__doc__) A simple example about class print(Myclass.__name__) Myclass print(Myclass.__dict__) {'__doc__': 'A simple example about class', '__init__': <function Myclass.__init__ at 0x7f0bf8fd0950>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Myclass' objects>, 'i': 123, '__dict__': <attribute '__dict__' of 'Myclass' objects>, 'f': <function Myclass.f at 0x7f0bf8fd08c8>} print(Myclass.__module__) __main__ print(Myclass.__bases__) (<class 'object'>,)
内置类 描述 __dict__ 类的属性 __doc__ 类的文档字符串 __name__ 类名 __module__ 类定义所在的模块 __bases__ 类的所有父类构成元素
1.3 实例化操作
# 实例化操作如下所示,赋值给一个变量,就能够创建一个实例对象 x=Myclass()
y=Myclass()
print(x.i)
123
print(x.f())
hello world
print(x.__doc__)
A simple example about class
# 创建的实例对象可以自由地绑定属性
x.iii="a9a"
print(x.iii)
a9a
# 创建的每个实例对象的内存地址都不一样
print(x)
<__main__.Myclass object at 0x7fbe7fa53160>
print(y)
<__main__.Myclass object at 0x7fbe7f7a8630>
1.4 __init__
# 上述的实例化操作创建了一个空的object # 但在很多情况下,我们创建实例对象时,可能都需要有特定的初始状态。这个由__init__方法实现。 # 当一个类定义了 __init__() 方法, 类在实例化时会自动调用 __init__() 方法, 用于创建新的类实例
class Myclass(object): '''A simple example about class''' i=123 def f(self): return "hello world" def __init__(self,name,score): self.name=name self.score=score # 关于__init__,要注意的是:
(1) __init__方法的第一个参数永远是self,表示创建的实例本身
(2) 有了__init__方法,在创建实例时就不能传入空的参数了,必须传入匹配的参数
x=Myclass() TypeError: __init__() missing 2 required positional arguments: 'name' and 'score' x=Myclass("J",11) print(x.name,x.score) J 11
2. 属性之“变量属性”、作用域问题、访问限制问题
2.1 类变量、实例变量、作用域
class test: x=7 #类的直接下级作用域的变量,叫做类变量 def __init__(self,name): self.name=name #实例中的变量,叫实例变量 instance1=test("name1") instance2=test('name2') # 类变量:既是类对象可见的属性、也是实例对象可见的属性 print(test.x) 7 print(instance1.x) 7 # 下面的例子中,instance1.x+=100本质是实例对象instance1新建了一个属性,覆盖了instance1.x这个变量 # 我们要知道,类变量可以是类对象的属性也可以是实例对象的属性,但实例对象的属性变化影响不了类对象的属性,也不会影响其他的实例对象 # 反之,类对象属性的变化倒是能影响实例对象的属性 test.x=100 print(instance1.x) 100 print(test.x) 100 instance1.x+=100 print(instance1.x) 107 print(test.x) 100 print(instance2.x) 100
2.2 访问限制
# 如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,就变成了一个私有变量(private),只有内部可以访问,外部不能访问 # 这样就确保了外部代码不能随意修改对象内部的状态,这样通过访问限制的保护,代码更加健壮 class Student(object): def __init__(self,name,score): self.__name=name self.__score=score stu=Student('J',100) print(stu.__score) AttributeError: 'Student' object has no attribute '__score' # 如果要允许外部访问者两个变量,可以增加get方法(get_name()和get_score()) # 如果又要允许外部修改这两个变量,可以增加set_score,虽然显得大费周折,但我们可以顺带对参数做个检查 class Student(object): def __init__(self,name,score): self.__name=name self.__score=score def get_name(self): return '{}'.format(self.__name) def get_score(self): return '{}'.format(self.__score) def print_stu(self): print('%s:%s' % (self.__name,self.__score)) def set_score(self,score): if 0<=score<=100: self.__score=score else: raise ValueError('bad score') stu=Student('J',100) print(stu.get_name()) J print(stu.get_score()) 100 stu.print_stu() J:100
stu.set_score(99);print(stu.get_score()) 99 stu.set_score(101) ValueError: bad score
3. 父类、子类(继承、多态)
# 基类/父类/超类(base class/super class) <—— 子类(subclass) class Animal(object): def run(self): print("Animal is running...") def run2(self): print("111") class Dog(Animal): def run(self): print("Dog is running...") class Cat(Animal): def run(self): print("Cat is running...") animal=Animal() dog=Dog() cat=Cat() # 子类父类存在同名方法时,子类方法覆盖父类方法 dog.run() Dog is running... dog.run2() 111 cat.run() Cat is running... # 可以通过isinstance(obj, class_or_tuple, /),可以判断一个instance object是否属于某个类 print(isinstance(dog,Dog)) True print(isinstance(dog,Animal)) True print(isinstance(animal,Dog)) False # issubclass(cls, class_or_tuple, /)class Base:
Public_class_var='public class var' #类变量(public) __Private_class_var='private class var' #类变量(private) def __init__(self): self.public_instance_var='public instance var' #实例变量(public) self.__private_instance_var='private instance var' #实例变量(private) def public_instance_method(self): return 'public instance method' def __private_instance_method(self): return 'private instance method' @classmethod def public_class_method(cls): return 'public class method' @classmethod def __private_class_method(cls): return 'private class method' @staticmethod def public_static_method(): return 'public static method' @staticmethod def __private_static_method(): return 'private static method' class Sub(Base): pass sub=Sub() print(sub.__dict__) {'_Base__private_instance_var': 'private instance var', 'public_instance_var': 'public instance var'}
# 子类可以继承类变量(public)、实例变量(public) class Sub(Base): def print_public_var(self): print(self.Public_class_var) def print_public_instance_var(self): print(self.public_instance_var) sub=Sub() sub.print_public_var() public class var sub.print_public_instance_var() public instance var # 事实上凡是公有的都能继承,凡是私有的都不能继承 class Sub(Base): def print_public_class_method(self): print(self.public_class_method()) def print_public_static_method(self): print(self.public_static_method()) def print_public_instance_method(self): print(self.public_instance_method()) sub=Sub() sub.print_public_class_method() public class method sub.print_public_static_method() public static method sub.print_public_instance_method() public instance method
4. classmethod、staticmethod
class A(object): def foo(self,x): print("executing foo({},{})".format(self,x)) @classmethod def class_foo(cls,x): print("executing class_foo({},{})".format(cls,x)) @staticmethod def static_foo(x): print("executing static_foo({})".format(x)) a=A() a.foo(1) executing foo(<__main__.A object at 0x7fe8619c7160>,1) a.class_foo(1) executing class_foo(<class '__main__.A'>,1) a.static_foo(1) executing static_foo(1) a.static_foo('hi') executing static_foo(hi) A.class_foo(1) executing class_foo(<class '__main__.A'>,1) A.static_foo(1) executing static_foo(1) A.foo(1)TypeError: foo() missing 1 required positional argument: 'x' print(a.foo) <bound method A.foo of <__main__.A object at 0x7f57d0ba41d0>> print(a.class_foo) <bound method A.class_foo of <class '__main__.A'>> print(a.static_foo) <function A.static_foo at 0x7f71b0c89b70>