單例設計模式、類方法、例項方法、靜態方法、修改類屬性
在python2中沒有宣告父類,則沒有父類,
在python3中沒有宣告父類,則父類為object,object為所有類的父類
類
: 1:例項屬性:
: 最好在__init__(self,…)中初始化
: 內部呼叫時都需要加上self.
: 外部呼叫時用instancename.propertyname
- 2:類屬性:
-
類屬性:(修改多個物件的某個特徵更加簡單,程式執行中)
: 在__init__()外初始化
: 在內部用classname.類屬性名呼叫
: 外部既可以用classname.類屬性名又可以用instancename.類屬性名來呼叫
3:私有屬性:
1):單下劃線_開頭:只是告訴別人這是私有屬性,外部依然可以訪問更改
2):雙下劃線__開頭:外部不可通instancename.propertyname來訪問或者更改, (Python不允許例項化的類訪問私有資料,但你可以使用 object._className__attrName 訪問屬性
: 實際將其轉化為了_classname__propertyname
子類繼承父類,繼承了父類的公有方法、屬性
dir(物件名):顯示物件的屬性和方法
dir(str)
dir(dict)
dir(tuple)
# 繼承也能呼叫私有的屬性和方法
class Person (object):
def __init__(self, name, age, money):
self.name = name
self.age = age
self.__money = money
def __step(self):
print(self)
class Women(Person):
pass
yang = Women('yue', 18, 1000)
print(dir(yang))
print(yang._Person__money)
yang._Person__step()
2 類屬性的重新賦值(唯一一種方式)
Python的類和類例項都是可變物件,可以隨時給屬性賦值,並且在原處修改。
在對類屬性進行修改時需要特別小心,因為所有的類例項都繼承共享類屬性,除非例項本身存在和類屬性同名的屬性。對類屬性進行修改,會影響到所有由這個類生成的例項。
class Person(object):
country = 'china'
pass
print(Person.country)
Person.country = 'yang'
print(Person.country)
修改類屬性
class People(object):
country = 'china' #類屬性
print(People.country) # 類名呼叫類屬性
p = People()
print(p.country) # 物件對用類屬性
p.country = 'japan'
print(p.country) # 例項屬性會遮蔽掉同名的類屬性
print(People.country)
del p.country # 刪除例項屬性
print(p.country)
china
china
japan
china
china
如果需要在類外修改類屬性,必須通過類物件去引用然後進行修改。如果通過例項物件去引用,會產生一個同名的例項屬性,這種方式修改的是例項屬性,不會影響到類屬性,並且之後如果通過例項物件去引用該名稱的屬性,例項屬性會強制遮蔽掉類屬性,即引用的是例項屬性,除非刪除了該例項屬性。
空值型別
# 空值型別
n = None
print(type(n)) # <class 'NoneType'>
print(id(n)) # 10353568 python已經開闢好的空間儲存當前的空值型別
print(None is False) # False
new
# __new__
#__new__方法才是真正的建構函式。
# 監聽物件建立成功並返回例項物件
def __new__(cls, *args, **kwargs):
return object.__new__(cls)
# init
# __init__ 方法為初始化方法,
# 監聽物件建立成功後,給物件新增屬性並賦值
#
#
# 追蹤通過這個類建立的物件的屬性值變化的
# 監聽記憶體地址的引用計數位0,(呼叫__del__監聽物件銷燬)
例子1:
# 單例設計模式:通過一個類創建出來的所有的物件的地址都是一樣的
# 如果想使用這個類建立的物件代表不同的事物,正常建立即可
# 如果只是想使用類中的方法,不關心物件是不同的物件,可以使用單例模式,(節約記憶體)
class Singleton(object):
# __country 類變數:可以通過類名、或者物件直接呼叫
__country = 'china'
# 定義一個類屬性儲存物件
instance = None
#
__is_first = True
def __new__(cls, *args, **kwargs):
# 判斷是否第一次建立物件,如果是則呼叫父類的__new__方法返回例項化出來的例項,
# 保證只有一個物件
if not cls.instance:
cls.instance = object.__new__(cls)
return cls.instance
def __init__(self, age, name):
if self.__is_first:
self.__name = name
self.age = age
self.__is_first = False
# cls -> class -> Person
@classmethod # 修飾器
def get_country(cls):
return cls.__country
def func(self):
print(self.__name)
@staticmethod
def hello():
print('hello')
a = Singleton(18, 'xizi')
b = Singleton(20, 'xiaojia')
print(id(a) == id(b)) # True 地址一樣,不建立新的物件
print(a.age)
print(b.age)
a.age = 19
print(a.age)
print(Singleton.get_country()) # china
print(a.func()) # 18 \n None, 函式執行完事之後,列印的話為None
print(Singleton)
例二
class HelloWorld():
def set(self, word):
self.word = word
def say_hello(self):
print(self.word)
class SingleCase(object):
def __new__(cls, *args, **kwargs):
if not hasattr(SingleCase, "_instance"):
cls._instance = super(SingleCase, cls).__new__(cls, *args, **kwargs)
cls._instance.hello = HelloWorld()
print("cls._instance.hello", id(cls._instance.hello))
cls._instance.hello.set("Hello world")
cls_addr = id(cls._instance)
print("cls_addr", cls_addr)
return cls._instance
def print(self):
self_addr = id(self)
instance_addr = id(self._instance)
print("self_addr", self_addr)
print("instance_addr", instance_addr)
self.hello.say_hello()
a = SingleCase()
b = SingleCase()
a.print()
print(id(a))
print(id(b))
"""output
cls._instance.hello 140312550013864
cls_addr 140312550013696
self_addr 140312550013696
instance_addr 140312550013696
Hello world
140312550013696
140312550013696
"""