文章彙總:http://www.javashuo.com/article/p-yofpeago-cs.htmlhtml
正文:git
代碼褲子:https://github.com/lotapp/BaseCode程序員
在線編程:https://mybinder.org/v2/gh/lotapp/BaseCode/master
在線預覽:http://github.lesschina.com/python/base/oop/2.繼承與多態.htmlangularjs
class Animal(object): def eat(self): print("動物會吃") class Cat(Animal): # 注意一下Python的繼承格式 pass class Dog(Animal): pass def main(): cat = Cat() dog = Dog() cat.eat() dog.eat() if __name__ == "__main__": main()
當聽到老師說:「 私有的屬性方法 不會被子類繼承 」的時候,小明內心一顫,聯想到以前講的 類屬性、 實例屬性、 實例方法、 類方法、 靜態方法,因而趕忙寫個Demo驗證一下:windows
class Animal(object): # 類屬性 name = '動物' def __init__(self): # 實例屬性 self.age = 1 def __bug(self): """實例私有方法""" print("我是動物類身上的私有方法:bug") def eat(self): """實例方法""" print("我是實例方法,動物會吃哦~") @classmethod def call(cls): """類方法""" print("我是類方法,動物會叫哦") @staticmethod def play(): """靜態方法""" print("我是靜態方法,動物會玩耍哦") class Dog(Animal): pass def main(): dog = Dog() # 實例屬性 print(dog.age) # 實例方法 dog.eat() # 類屬性 print(dog.name) # 類方法 dog.call() Dog.call() Animal.call() # 靜態方法 dog.play() Dog.play() Animal.play() if __name__ == '__main__': main()
來張圖就懂了,不是 私有的 都能訪問:
這時候,小明老高興了,單回頭一想 ==> 不科學啊,dog應該有其對應的方法吧,C#有 虛方法重寫,Python怎麼搞?在 子類裏面又 怎麼調用父類方法呢?
對於小明的提示老師很高興,因而點名小潘來寫一個子類調用父類的demo(老師昨天從窗戶裏看見小潘有預習):
# 調用父類的方法
class Father(object): def eat(self): print("文雅的吃飯") class Son(Father): def eat(self): # 調用父類方法第1種(super().方法) super().eat() class GrandSon(Son): def eat(self): # 調用父類方法第2種(記得傳self) Son.eat(self) def main(): xiaoming = Son() xiaoming.eat() xiaoli = GrandSon() xiaoli.eat() if __name__ == '__main__': main()
通常咱們使用 super().方法
來調用父類方法
第二種方法 類名.方法(self)
千萬別忘記傳self哦
對了,C#是用base關鍵詞,別搞混了
小明這時候可不高興了,風頭怎麼能被小潘所有搶走呢,趕忙問問旁邊一樣預習的偉哥
不一下子淡定的發了份重寫父類方法的demo給老師:
# 重寫父類方法==>子類和父類有同名方法
class Father(object): def __init__(self, name): self.name = name def eat(self): print("%s喜歡文雅的吃飯" % self.name) class Son(Father): def __init__(self, name): super().__init__(name) def eat(self): print("%s喜歡大口吃飯大口喝酒" % self.name) def main(): xiaoming = Father("小明") xiaoming.eat() xiaopan = Son("小潘") xiaopan.eat() if __name__ == "__main__": main()
# 多繼承引入
class Father(object): def eat(self): print("文雅的吃飯") class Mom(object): def run(self): print("小碎步") class Son(Father, Mom): pass def main(): son = Son() son.eat() son.run() if __name__ == '__main__': main()
繼承能夠把父類的全部功能都直接拿過來,這樣就沒必要重0開始寫代碼,子類只須要新增本身特有的方法,也能夠把父類不適合的方法覆蓋重寫
注意一個狀況,若是父類裏面有同名方法咋辦了?到底調哪一個呢?
使用 子類名.__mro__
能夠看在調方法的時候搜索順序
通常同名方法都是 先看本身有沒有,而後看繼承順序,好比這邊 先看Mom再看Father
# 若是父類裏面有同名方法怎麼知道調哪一個?
class Father(object): def eat(self): print("文雅的吃飯") class Mom(object): def eat(self): print("開心的吃飯") class Son(Mom, Father): pass def main(): son = Son() son.eat() print(Son.__mro__) # 通常同名方法都是先看本身有沒有,而後看繼承順序,好比這邊先看Mom再看Father if __name__ == '__main__': main()
Python的多繼承最好是當C#或者Java裏面的接口使用,這樣結構不會混亂( 特殊狀況除外)
來個例子:
class Animal(object): pass class Flyable(object): """飛的方法""" pass class Runable(object): """跑的方法""" pass class Dog(Animal, Runable): pass class Cat(Animal, Runable): pass class Bird(Animal, Flyable): pass class Dack(Animal, Runable, Flyable): """鴨子會飛也會跑""" pass
和C#同樣,Python的 父類構造函數不會被繼承
其實從資源角度也不該該被繼承,若是有1w個子類,那每一個子類裏面都有一個父類方法,想一想這是多麼浪費的一件事情?
2.3.C#繼承
下課後,小明認真思考總結,而後對照Python寫下了C#版的繼承:
定義一我的類
public class Person { public string Name { get; set; } public ushort Age { get; set; } public Person(string name, ushort age) { this.Name = name; this.Age = age; } public void Hi()//People { Console.WriteLine("Name: " + this.Name + " Age: " + this.Age); } public virtual void Show()//People { Console.WriteLine("Name: " + this.Name + " Age: " + this.Age); } }
定義一個學生類
public class Student : Person { #region 屬性 /// <summary> /// 學校 /// </summary> public string School { get; set; } /// <summary> /// 班級 /// </summary> public string StrClass { get; set; } /// <summary> /// 學號 /// </summary> public string StrNum { get; set; } #endregion #region 構造函數 /// <summary> /// 調用父類構造函數 /// </summary> /// <param name="name"></param> /// <param name="age"></param> public Student(string name, ushort age) : base(name, age) { } public Student(string name, ushort age, string school, string strClass, string strNum) : this(name, age) { this.School = school; this.StrClass = strClass; this.StrNum = strNum; } #endregion /// <summary> /// new-隱藏 /// </summary> public new void Hi()//Student { Console.WriteLine("Name: " + this.Name + " Age: " + this.Age + " School: " + this.School + " strClass: " + this.StrClass + " strNum: " + this.StrNum); } /// <summary> /// override-覆蓋 /// </summary> public override void Show()//Student { Console.WriteLine("Name: " + this.Name + " Age: " + this.Age + " School: " + this.School + " strClass: " + this.StrClass + " strNum: " + this.StrNum); } }
調用一下:
Person p = new Student("app", 10, "北京大學", "001", "01001"); p.Hi(); p.Show(); Console.WriteLine(); Student s = p as Student; s.Hi(); s.Show();
結果:
Name: app Age: 10 Name: app Age: 10 School: 北京大學 strClass: 001 strNum: 01001 Name: app Age: 10 School: 北京大學 strClass: 001 strNum: 01001 Name: app Age: 10 School: 北京大學 strClass: 001 strNum: 01001
2.4C#接口的多實現
定義兩個接口:
public interface IRun { //什麼都不用加 void Run(); } public interface IEat { void Eat(); }
定義一個Dog類來實現兩個接口,這樣dog就有了run和eat的方法了
var dog = new Dog(); dog.Eat(); dog.Run();
結果:
狗狗吃 狗狗跑
3 多態
3.1.Python
說多態以前說說類型判斷,之前咱們用 type()
or isinstance()
判斷一個變量和另外一個變量是不是同一個類型==> type(a)==type(b)
判斷一個變量是不是某個類型==> type(a)==A
or isinstance(a,A)
# 判斷一個變量是不是某個類型 ==> isinstance() or type
class Animal(object): pass class Dog(Animal): pass def main(): dog = Dog() dog2 = Dog() print(type(dog) == Dog) print(type(dog) == type(dog2)) print(type(dog)) print(isinstance(dog, Dog)) print(isinstance(dog, Animal)) # arg 2 must be a type or tuple # print(isinstance(dog, dog2)) if __name__ == '__main__': main()
小明老高興了,終於講解多態了,不由問道:「 多態的好處是啥?」
小潘瞥了一眼小明~「廢話,確定爲了 屏蔽子類差別用的啊,像簡單工廠不就乾的這個事?"
小明楞了楞,眼巴巴的看着老師繼續講課。
設計模式咱們會找個專題講講,如今給大家說的是Python的基礎。
Python是動態語言的「 鴨子類型」,它並不要求嚴格的繼承體系。
一個對象只要「看起來像鴨子,走起路來像鴨子」,那它就能夠被看作是鴨子(最後會貼一個案例)
C#實現多態有不少方式,好比虛方法,好比抽象類,好比接口等等...
小明迷迷糊糊的問道:「那 Python怎麼實現多態呢?」
老師看了一眼打斷他講課的小明,而後繼續說道~來個簡單案例:
class People(object): def eat(self): print("人類會吃飯") class Father(object): def eat(self): print("優雅的吃飯") class Teacher(object): def eat(self): print("趕時間的吃飯") # C# 或者 Java裏面 寫成 eat(People obj) def eat(obj): obj.eat() def main(): teacher = Teacher() father = Father() eat(teacher) eat(father) if __name__ == '__main__': main()
多態的好處在於,若是這時候我再來個Son子類,有eat()方法編寫正確,不用管原來的代碼是如何調用的
此次小明懂了,爲了裝一下,說道:」老師老師,我記得C# 或者 Java裏面是寫成 eat(People obj) 的吧?「
老師欣慰的笑了一下,說道:」記得剛纔說的 填鴨式
嗎?Python這麼寫有個好處哦,咱們來看個案例,而後你本身總結「
class People(object): def eat(self): print("人類會吃飯") class Father(object): def eat(self): print("優雅的吃飯") class Teacher(object): def eat(self): print("趕時間的吃飯") class Dog(object): def eat(self): print("舔着吃") def eat(obj): obj.eat() def main(): teacher = Teacher() father = Father() eat(teacher) eat(father) # 咱們添加一個不是People子類的Dog類,只要有eat方法,參數同樣就能夠直接調 dog = Dog() eat(dog) if __name__ == '__main__': main()
小明忽然大聲說道:」老師老師,我知道了,Python這是吧類的繼承和接口繼承融合起來了啊,實現多態就至關於C#裏面的接口實現多態啊!!!「
老師點評道:」你姑且能夠這麼理解,這些咱們後面還會繼續說的,這種填鴨式的手段剛開始的確會有點不方便,用着用着你就會以爲挺方便的「
小明認真思考總結,而後對照Python和小潘一塊兒寫下了 C#版的多態:
3.2.C#虛方法實現多態
定義一我的類:
public class Person { #region 字段+屬性 /// <summary> /// 姓名 /// </summary> private string _name; public string Name { get { return _name; } set { _name = value; } } /// <summary> /// 性別 /// </summary> private bool _gender; public bool Gender { get { return _gender; } set { _gender = value; } } /// <summary> /// 年齡 /// </summary> public short Age { get; set; } #endregion #region 構造函數 public Person() { } public Person(string name, bool gender) { this.Name = name; this.Gender = gender; } public Person(string name, bool gender, short age) : this(name, gender) { this.Age = age; } #endregion #region 方法 /// <summary> /// 打招呼 /// </summary> public virtual void SaiHi() { Console.WriteLine("我是一我的類!"); } #endregion }
定義一個女孩類:
public class Gril : Person { #region 構造函數 public Gril() { } public Gril(string name, bool gender) : base(name, gender) { } public Gril(string name, bool gender, short age) : base(name, gender, age) { } #endregion /// <summary> /// 重寫父類方法 /// </summary> public override void SaiHi() { string genderStr = Gender == true ? "男孩" : "女孩"; Console.WriteLine($"你好,我叫{Name},今年{Age}歲了,我是一個靦腆的小{genderStr}"); } }
定義一個男孩類:
public class Boy : Person { #region 構造函數 public Boy() { } public Boy(string name, bool gender) : base(name, gender) { } public Boy(string name, bool gender, short age) : base(name, gender, age) { } #endregion //public void SaiHi() public override void SaiHi() { string genderStr = Gender == true ? "男孩" : "女孩"; Console.WriteLine($"你好,我叫{Name},今年{Age}歲了,我是一個靦腆的小{genderStr}"); } }
調用:
static void Main(string[] args) { Person[] persons = { new Person(), new Boy("鐵鍋", true, 13), new Gril("妞妞", false, 22) }; foreach (var item in persons) { //看看item裏面到底放的是什麼 Console.WriteLine(item.ToString()); item.SaiHi(); Console.WriteLine(); } }
結果:
Polymorphism1.Person 我是一我的類! Polymorphism1.Boy 你好,我叫鐵鍋,今年13歲了,我是一個靦腆的小男孩 Polymorphism1.Gril 你好,我叫妞妞,今年22歲了,我是一個靦腆的小女孩
3.3.C#抽象類實現多態
定義一個動物類:
public abstract class Animal { /// <summary> /// 抽象類中能夠有正常的方法 /// </summary> public void Action() { Console.WriteLine("動物能夠動"); } /// <summary> /// 抽象方法必須在抽象類中 /// </summary> public abstract void Call(); }
定義一個貓科動物類(子類必須實現父類抽象方法,若是不實現,那麼該類也必須是抽象類)
/// <summary>
/// 貓科動物---子類必須實現父類抽象方法,若是不實現,那麼該類也必須是抽象類 /// </summary> public abstract class Feline : Animal { }
定義一個貓類
public class Cat : Feline { /// <summary> /// 子類必須實現父類抽象方法,若是不實現,那麼該類也必須是抽象類 /// </summary> public override void Call() { Console.WriteLine("喵喵叫~~~"); } }
定義一個狗類
public class Dog : Animal { /// <summary> /// 子類必須實現抽象類中的抽象方法 /// </summary> public override void Call() { Console.WriteLine("汪汪叫~~~"); } }
調用:
Animal[] animals = { new Dog(), new Cat() }; foreach (var item in animals) { item.Call(); }
結果:
汪汪叫~~~ 喵喵叫~~~
3.4.C#接口實現多態
定義一個跑的接口:
public interface IRun { /// <summary> /// 接口中能夠聲明屬性,方法,索引器等 /// </summary> //string Name { get; set; } void Runing(); }
定義一個貓類:
public class Cat : IRun { public void Runing() { Console.WriteLine("飛快的跑着上樹"); } }
定義一個學生類:
public class Student : IRun { public void Runing() { Console.WriteLine("飛快的跑着去上課"); } }
調用:
IRun[] objs = { new Student(), new Cat() }; foreach (var item in objs) { item.Runing(); }
結果:
飛快的跑着去上課 飛快的跑着上樹
Python3 與 C# 面向對象之~封裝
文章彙總:http://www.javashuo.com/article/p-yofpeago-cs.html
正文:
最新彩版:http://www.javashuo.com/article/p-purcxavn-d.html
在線編程:https://mybinder.org/v2/gh/lotapp/BaseCode/master
在線預覽:http://github.lesschina.com/python/base/oop/1.封裝.html
此次儘可能用故事模式來說知識,上次剛說美化,此次算是第一篇了。步入正題:
1.定義一個類
類的組成:類名、屬性(沒有字段)、方法
1.1建立一個類
# 類名首字母大寫
class Student(object): """建立一個學生類""" # 沒有屬性定義,直接使用便可 # 定義一個方法,方法裏面必須有self(至關於C#的this) def show(self): print("name:%s age:%d"%(self.name,self.age))
# 實例化一個張三
zhangsan=Student() # 給name,age屬性賦值 zhangsan.name="張三" zhangsan.age=22 # 調用show方法 zhangsan.show()
# 打印一下類和類的實例
print(Student) print(zhangsan) #張三實例的內存地址:0x7fb6e8502d30
和靜態語言不一樣,Python容許對實例變量綁定任何數據 ==> 對於兩個實例變量,雖然它們都是同一個類的不一樣實例,但擁有的變量名稱可能都不一樣
說的比較抽象,舉個例子就明瞭了:
xiaoming=Student("小明",22) xiaoming.mmd="mmd" print(xiaoming.mmd) # 小明和小潘都是Student類,可是小明有的mmd屬性,小潘卻沒有 xiaopan=Student("小潘",22) print(xiaopan.mmd)
class Student(object): # 初始化賦值 def __init__(self,name,age): self.name=name self.age=age def show(self): print("name:%s age:%d"%(self.name,self.age))
# 有了__init__方法,在建立實例的時候,就不能傳入空的參數了
lisi=Student()
# 建立一個正確的實例
xiaowang=Student("小王",22) xiaowang.show()
# Python的__str__()方法
class Student(object): def __init__(self, name, age): self.name = name self.age = age # self別忘記寫了,return也別忘了 def __str__(self): return "姓名:%s,年齡:%s" % (self.name, self.age)
lisi = Student("李四", 22) print(lisi) #如今打印就是你DIV的輸出了
class Student(object): def __init__(self, name, age): self.name = name self.age = age def get_name(self): return self.name def set_name(self, name): self.name = name def get_age(self): return self.age def set_age(self, age): if age > 0: self.age = age else: print("age must > 0") def show(self): print("name:%s,age:%d" % (self.name, self.age))
小明心想,想要修改age屬性,你經過set_age我就能夠判斷了哇,仍是本寶寶聰明
這時候小潘過來了,淡淡的一笑,看我怎麼破了你 ~ 看代碼:
zhangsan = Student("張三", -20) zhangsan.show() # name:張三,age:-20 zhangsan.age = -1 # set_age方法形同虛設,我徹底能夠直接訪問字段了 zhangsan.show() # name:張三,age:-1
小潘傲氣的說道~大叔,給你臉呢。我就是不去訪問你設定的方法怎麼滴呢?
小明急的啊,趕忙去找偉哥求經。不一會,傲氣的貼出本身的New Code,心想着我私有屬性都用上了還怕個毛毛:
class Student(object): def __init__(self, name, age): self.__name = name # 通常須要用到的屬性都直接放在__init__裏面了 # self.__age = age self.set_age(age) def get_name(self): return self.__name def set_name(self, name): self.__name = name def get_age(self): return self.__age def set_age(self, age): if age > 0: self.__age = age else: print("age must > 0") def show(self): print("name:%s,age:%s" % (self.__name, self.__age))
小潘冷笑道~呵呵,而後使用了上次的絕招:
zhangsan = Student("張三", -20) zhangsan.__age = -1 # 一樣的代碼,只是屬性前面加了下劃線 zhangsan.show()
此次小潘同志傻眼了,徹底不能訪問了啊?不行,怎麼能被小明大叔笑話呢?
因而上網翻資料,國內不行就國外,外文很差就翻譯,終於找到一個新破解方式:
雙下劃線開頭的實例變量不能直接訪問,是由於Python解釋器對外把__age變量改爲了_Studentage,因此,仍然能夠經過**_Studentage**來訪問:
# 搞事情
zhangsan._Student__age = -1 zhangsan.show()
建議你不要這麼幹,不一樣版本的Python解釋器可能會把__age改爲不一樣的變量名
有些時候,你會看到以一個下劃線開頭的實例變量名,好比_age這樣的實例變量,外部是能夠訪問的。
可是,請把它視爲私有變量,不要隨意訪問(Python不少東西全憑自覺~捂臉@_@)
小潘終於長嘆一口氣,而後還不忘取笑小明同窗~你這屬性搞的,真麻煩,老是經過方法調用,太累了 <_> 鄙視!
這可把小明急的啊,學習的積極性都沒有了,吃了碗牛肉麪就去偉哥那邊好好取經了~
# 私有方法一筆帶過
class Student(object): """私有方法""" def __go_home(self): pass zhangsan = Student() zhangsan.__go_home() # 訪問不到
class Student(object): def __init__(self, name, age): # 通常須要用到的屬性都直接放在__init__裏面了 self.name = name self.age = age @property def name(self): return self.__name @name.setter def name(self, name): self.__name = name @property def age(self): return self.__age @age.setter def age(self, age): if age > 0: self.__age = age else: print("age must > 0") def show(self): print("name:%s,age:%s" % (self.name, self.age))
xiaoming = Student("小明", 22) xiaoming.name = "小潘" xiaoming.age = -2 xiaoming.show()
把一個getter方法變成屬性,只須要加上@property
就能夠了
@方法名.setter
,負責把一個setter方法變成屬性賦值
固然了,若是隻想讀 ==> 就只打上@property
標籤
小明同窗高興壞了,趕忙大吃了一頓~
1.6 __del__ and __new__
建立對象後,python解釋器默認調用__init__() 方法
當刪除一個對象時,python解釋器也會默認調用__del__() 方法(有點析構函數的味道)
當有1個變量保存了對象的引用時,此對象的引用計數就會加1
當使用del刪除變量指向的對象時,若是對象的引用計數不爲1,那麼每次刪除計數減1,當計數爲1的時候再調del就真把對象刪了
這個能夠結合我以前說過的連接來理解:於連接文件的探討
看着老師誇誇其談,小明愣了楞,摸摸肚子想到,真BB,我先搞個例子練練:
# 定義一個臨時類
class Temp(object): def __del__(self): print("你被幹掉了")
驗證方面用編輯器比較合適,交互模式下可能不是真正的結果
# 對象被s1和s2引用
s1 = Temp() s2 = s1 del s1 # 只刪除s1,新建立的對象並無被刪除 print("-" * 10)
輸出:(最後的被幹掉是程序退出了)
# ---------- # 你被幹掉了
若是用連接來解釋就是這樣的:
此次兩個都刪掉:
t1 = Temp() t2 = t1 del t1 del t2 print("-" * 10)
輸出:
# 你被幹掉了 # ----------
都刪了,天然就真刪掉了
這樣搞比較麻煩,咱們引入一下獲取引用個數:getrefcount(object也會佔1個引用計數)來個案例:
# 程序退出的時候,在他運行期間全部佔用資源歸還操做系統
# 引用計數 import sys t1 = Temp() print(sys.getrefcount(t1)) #(結果比實際引用大1)【object也會佔1個引用計數】 t2 = t1 print(sys.getrefcount(t1)) print(sys.getrefcount(t2)) del t1 print(sys.getrefcount(t2)) # sys.getrefcount(t1)#被刪掉天然沒有了 del t2 print("-" * 10)
運行結果:
2 3 3 2 你被幹掉了 ----------
我再貼一種狀況,你能夠思考下爲啥:
t1 = Temp() t2 = Temp() del t1 del t2 print("-" * 10)
輸出:
# 你被幹掉了 # 你被幹掉了 # ----------
小潘扭過頭瞅了一眼說道:「大叔,你__new__忘記寫案例了」
小明一愣神,立馬反應過來講:「我這叫謀然後動~」
當你實例化一個對象的時候,就會執行new 方法裏面的方法。new方法在類定義中不是必須寫的,若是沒定義,默認會調用object.new去建立一個對象
__new__方法中至少要有一個參數cls,表明要實例化的類,此參數在實例化時由Python解釋器自動提供
__new__方法中必需要有返回值(返回實例化出來的實例)
小明翻閱了官方文檔,淡定的打下了以下標準格式的代碼:
class Dog(object): def __init__(self, name): self.name = name print("初始化完畢") def __str__(self): return "Dog的名字叫:%s" % self.name def __new__(cls, name): # 注意參數,是cls,而後其餘參數和init保持一致便可 print("建立對象完畢") # 別忘記寫返回值哦 return object.__new__(cls) def main(): happy = Dog("Happy") print(happy) if __name__ == '__main__': main()
關於__name__在模塊調用的時候會詳細說,你能夠先這樣理解:若是直接運行py文件就執行,別人調用那麼你的main就不執行了
標準寫法:
# 1.導入的模塊
# 2.class的定義 # 3.其餘方法定義 def main(): pass if __name__ == '__main__': main()
其餘內容後面會繼續說,封裝部分再說說靜態方法和類方法之類的就結束了(和C#仍是有很大區別的)
1.7 類屬性、實例屬性
小明問老師:「老師老師,怎麼沒有靜態類,靜態屬性之類的東西呢?」
老師笑而不語道:「小傢伙原來不只僅是體重增長啊,這求知慾也是大大的增長呢 ~ 且聽我慢慢道來」
類在程序裏面也是對象(你姑且能夠認爲全部的類都相似於C#裏面的靜態類),而經過類實例化的對象,叫實例化對象
實例屬性 --> 實例對象相互之間不共享 通常咱們都是在__init__
中定義
類屬性(相似於C#裏面的靜態字段) --> 屬於類對象,多個實例對象之間共享
注意一下:相同名稱的實例屬性將屏蔽掉類屬性(儘可能別同名)
類屬性除了能夠經過 類名.類屬性 訪問外,還能夠直接 實例對象.類屬性 (C#中抽象類和靜態類是不能被實例化的)
來個案例更直觀點:
class Person(object): # age爲類屬性 age = 1 def __init__(self, name): # name爲實例屬性 self.name = name def main(): # 類名.類屬性 print(Person.age) xiaoming = Person("小明") # 對象.類屬性 print(xiaoming.age) if __name__ == '__main__': main()
若是須要在類外 修改類屬性,必須經過類對象去引用而後進行修改
若是經過實例對象去引用,會產生一個同名的實例屬性,這種方式修改的是實例屬性,不會影響到類屬性
若是經過實例對象去引用該名稱的屬性,實例屬性會強制 屏蔽掉類屬性,即引用的是實例屬性,除非del了該實例屬性才能正常訪問類屬性
你能夠理解爲,Python這麼作只是爲了方便你獲取,該怎麼修改還得怎麼作。來看個案例:
class Person(object): # age爲類屬性 age = 1 def __init__(self, name): # name爲實例屬性 self.name = name def main(): # 類名.類屬性 print(Person.age) # 經過對象.類屬性修改 xiaoming = Person("小明") xiaoming.age = 100 print(xiaoming.age) # 其實,並無修改爲功,只是產生了一個同名age print(Person.age) # 對吧,類屬性並無被修改 # 經過類名修改 Person.age = 22 # 若是須要在類外修改類屬性,必須經過類對象去引用而後進行修改 print(xiaoming.age) # 剛纔已經建立一個同名age,因此如今顯示的是剛纔的值 print(Person.age) # 經過類名.類屬性 就能夠看到值被修改了 # 若是你仍是不信,能夠建立一個新對象看看 xiaopan = Person("小潘") print(xiaopan.age) # xiaoming實例對象想訪問怎麼辦? # 除非del了該實例屬性才能正常訪問類屬性 del xiaoming.age print(xiaoming.age) # 這時候訪問的就是 類屬性 了 if __name__ == '__main__': main()
class Dog(object): # 類屬性 name = "小汪" # 實例方法 def __init__(self, age): # 實例屬性 self.age = age # 打印看看 print("self id:%s" % id(self)) # 類方法 @classmethod def show_name(cls): # 訪問類屬性 cls.xxx print("我叫%s" % cls.name) # 打印看看 print("cls id:%s" % id(cls)) # 靜態方法 @staticmethod def say_hello(): print("汪汪汪") def main(): # 類名方式訪問 Dog.show_name() Dog.say_hello() # 類名的方式能夠訪問靜態方法 # 實例對象方式訪問 dog = Dog(2) dog.show_name() dog.say_hello() if __name__ == '__main__': main()
通常都是這樣用的(供參考):
實例方法:通常平時用的都是它
類方法:類方法用在模擬C#多個構造函數(Python裏面不能有同名函數) or 你須要 對類屬性、類方法操做之類的
靜態方法:通常 都是獨立功能,相似於函數,只不過在面向對象裏面通常這麼用
1.9 C#封裝案例
C#面向對象比較優美,來個封裝的案例基本上就搞定了:
using System; namespace _1Encapsulation { public class Student { /// <summary> /// 字段 /// </summary> private int _age; /// <summary> /// 屬性 /// </summary> public int Age { get { return _age; } set { if (value > 1) { _age = value; } } } /// <summary> /// 自動化屬性 /// </summary> public string Name { get; set; } /// <summary> /// 自動屬性必需要有get訪問器 /// </summary> public string SNum { get; } private int _gender; public int Gender { set { _gender = value; } } /// <summary> /// 構造函數的名字必須與類名一致 /// 構造函數沒有返回值也沒有viod /// 默認自動生成一個無參構造函數,當有一個有參構造函數的時候無參構造函數便不會自動建立 /// </summary> public Student() { } /// <summary> /// 有參構造函數 /// </summary> /// <param name="name"></param> /// <param name="age"></param> public Student(string name, int age) { this.Name = name; this.Age = age; } /// <summary> /// this調用當前類的某個有參構造函數 /// </summary> /// <param name="name"></param> /// <param name="age"></param> /// <param name="gender"></param> public Student(string name, int age, int gender) : this(name, age) { this.Gender = gender; } /// <summary> /// 某個方法 /// </summary> public void Show() { Console.WriteLine("Name:" + this.Name + " Age:" + this.Age + "\n"); } public override string ToString() { return "Name:" + this.Name + " Age:" + this.Age; } } }
調用部分:
using System; namespace _1Encapsulation { class Program { static void Main(string[] args) { Student s = new Student() { Name = "mmd", Age = 13, Gender = 1 }; s.Show(); Student s1 = new Student("dmm", 20); s1.Show(); Console.WriteLine(s); } } }
Python3 與 NetCore 基礎語法對比(Function專欄)
文章彙總:http://www.javashuo.com/article/p-yofpeago-cs.html
彙總系列:http://www.javashuo.com/article/p-dojeygnv-gw.html
最新彩色版:http://www.javashuo.com/article/p-obgfrmjz-g.html
昨晚開始寫大綱作demo,今天犧牲中午休息時間碼文一篇,但願你們點點贊 O(∩_∩)O
NetCore:https://github.com/lotapp/BaseCode/tree/master/netcore/1_POP/6func
Python:https://github.com/lotapp/BaseCode/tree/master/python/1.POP/4.func_IO
在線演示:http://nbviewer.jupyter.org/github/lotapp/BaseCode/tree/master/python/notebook/1.POP/4.func
主要是普及一下Python基礎語法,對比着Net,新手更容易上手。對比學習頗有意思的,尤爲是一些底層和思路
原本感受函數要說的地方沒多少,細細一規劃,發現~仍是單獨拉出一篇說說吧,以後就進入面向對象了,函數仍是有必要了解一下的,否則到時候Class裏面的方法定義又要說了。
演示的模式一直在變,剛開始讓你們熟悉一下VSCode,後來引入了ipython交互式編程的概念,如今就用前幾天講的Notebook來演示了(VSCode如今也有這個預覽版的插件了)
直接跳到擴展系列:http://www.javashuo.com/article/p-obgfrmjz-g.html
先從函數定義提及吧:
# 定義一個空函數:(不寫pass就報錯了)
# 定義一個無參函數(注意縮進)
# 定義一個含參函數
擴:文檔說明用""" 或者'''來定義,就是以下效果
# 定義一個含默認參數(缺省參數)的函數
# 定義有返回值的函數
# 定義含有多個返回值的函數(利用了元組)
來個案例解釋一下:(多返回值只是一種假象,Python函數返回的仍然是單一值~元組)
傳多個參數系列:(上面那個多返回參數也能夠返回一個list來實現相似效果)
引用傳遞(經過元組、列表實現):擴展有可變類型和不可變類型做爲形參的對比
# 定義一個可變參數的函數(參數名字通常都是*args)
若是你須要傳一個元組或者列表進去的話,能夠參數前面加*
# 定義含關鍵字參數的函數:def default_kv_params(name,age=23,**kv):# 可變參數容許你傳入0個或任意個參數,這些可變參數在函數調用時自動組裝爲一個tuple
# 關鍵字參數容許你傳入0個或任意個含key-value的參數,自動組裝爲一個dict
來個綜合案例:def default_god_params(name,age=23,*args,**kv):
須要注意py裏面的書寫格式==》先定義再調用( Code參考)![]()
NetCore:(C#基礎語法你們都很熟了,我貼一個註釋的Code便可)VSCode裏面若是也想像VS同樣,///就生成註釋==》請安裝函數文檔註釋:XML Documentation Comments
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141using
System;
using
System.Collections.Generic;
namespace
_6func
{
class
Program
{
static
void
Main(
string
[] args)
{
#region Base
// # 定義一個空函數:
Method();
// # 定義一個無參函數
GetName();
// # 定義一個含參函數
ShowInfos(
"李四"
, 22);
// # 定義一個含默認參數(缺省參數)的函數
DefaultParam(
"張三"
);
// # 定義有返回值的函數
int
result = DivHaveReturn(1, 2);
Console.WriteLine($
"計算結果爲{result}"
);
#endregion
// # 定義含有多個返回值的函數(利用了元組)
var
(sum, dvalue) = DivHaveReturns(1, 2);
Console.WriteLine($
"sum:{sum},D-value:{dvalue}"
);
// 傳多個參數系列:
// 引用傳遞(經過元組、列表實現):擴展有可變類型和不可變類型做爲形參的對比
var
list =
new
List<
int
>() { 1, 2, 3, 4, 5 };
Console.WriteLine(DefaultSomeParams(list));
Console.WriteLine(list.Count);
//這就是引用傳遞的證實
// # 定義一個可變參數的函數(參數名字通常都是*args)
Console.WriteLine(DefaultParams(1, 2, 3, 4, 5));
// # 定義含關鍵字參數的函數 直接傳Dict
}
#region base
/// <summary>
/// 定義一個空函數
/// </summary>
private
static
void
Method()
{
}
/// <summary>
/// 定義一個無參函數
/// </summary>
// private static void GetName()
// {
// Console.WriteLine("你好");
// }
//簡寫
private
static
void
GetName() => Console.WriteLine(
"你好"
);
/// <summary>
/// 定義一個含參數的函數
/// </summary>
/// <param name="name">名字</param>
/// <param name="age">年齡</param>
// private static void ShowInfos(string name, int age)
// {
// Console.WriteLine($"我叫{name} 個人年齡是{age}");
// }
//簡寫
private
static
void
ShowInfos(
string
name,
int
age) => Console.WriteLine($
"我叫{name} 個人年齡是{age}"
);
/// <summary>
/// 定義一個含缺省參數的函數
/// </summary>
/// <param name="name">名字</param>
/// <param name="age">年齡默認23</param>
// private static void DefaultParam(string name, int age = 23)
// {
// Console.WriteLine($"我叫{name} 個人年齡是{age}");
// }
//簡寫
private
static
void
DefaultParam(
string
name,
int
age = 23) => Console.WriteLine($
"我叫{name} 個人年齡是{age}"
);
/// <summary>
/// 定義一個有返回值的函數(計算a+b,返回計算結果)
/// </summary>
/// <param name="a">num1</param>
/// <param name="b">num2</param>
// private static int DivHaveReturn(int a, int b)
// {
// return a + b;
// }
//簡寫
private
static
int
DivHaveReturn(
int
a,
int
b) => a + b;
#endregion
/// <summary>
/// 定義含有多個返回值的函數(利用了元組)
/// 計算a+b的和,計算a-b,並返回兩個結果
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
// private static (int sum,int dValue) DivHaveReturns(int a, int b)
// {
// return ((a+b),(a-b));
// }
//簡寫
private
static
(
int
sum,
int
dValue) DivHaveReturns(
int
a,
int
b) => ((a + b), (a - b));
#region 傳入多個參數系列
/// <summary>
/// 利用列表實現,引用傳遞之類的C#還有ref和out,這邊就不說了
/// </summary>
/// <param name="nums"></param>
/// <returns></returns>
private
static
int
DefaultSomeParams(List<
int
> numList)
{
int
sum = 0;
foreach
(
var
item
in
numList)
{
sum += item;
}
numList.Clear();
return
sum;
}
/// <summary>
/// 定義一個可變參數的函數
/// </summary>
/// <param name="args"></param>
/// <returns></returns>
private
static
int
DefaultParams(
params
int
[] args)
{
int
sum = 0;
foreach
(
var
item
in
args)
{
sum += item;
}
return
sum;
}
#endregion
}
}
1.遞歸函數:函數遞歸調用其實就是本身調用本身,關鍵點只要考慮何時跳出便可(沒有跳出就是死循環)先來個簡單的案例熟悉一下:
來個案例(實際工做中並不會本身定義,用系統自帶 strip方法便可)
C#的遞歸我就引用一下之前的Code: https://github.com/dunitian/LoTCodeBase/blob/master/NetCode/1.面向過程/01.基礎/10.遞歸案例/Program.cs![]()
2.匿名函數系列:lambda 參數: 表達式
來個常常用的案例:data_list.sort(key=lambda x:x["key"])
還有一個比較經常使用的地方:(當參數傳遞)
NetCore:上面Code中的簡寫都是用匿名函數的方式,能夠參考
3.全局變量和局部變量有人可能會說,這個就太簡單了,沒啥好說的,(⊙o⊙)… Python還真須要說說,來個案例給你猜結果:
直接看結果吧:發現全局變量a木有被修改,而b修改了
仍是來個簡單案例說明下吧~![]()
# 這是由於,python定義一個變量的寫法不用加類型致使的(⊙﹏⊙) 因此函數裏面a=200,python解釋器就認爲你定義了一個和a這個全局變量名字相同的局部變量,那怎麼用呢?global來聲明一下全局變量便可:
總結:# 在函數中不使用global聲明全局變量不能修改全局變量==>本質是不能修改全局變量的指向,即不能將全局變量指向新的數據# 對於不可變類型的全局變量來講,因其指向的數據不能修改,因此不使用global時沒法修改全局變量# 對於可變類型的全局變量來講,因其指向的數據能夠修改,因此不使用global時也可修改全局變量
下面就進入驗證擴展系列,看看一些概念:# 以前不少資料說py3匿名函數裏不能調用print函數,本身測試下![]()
# 可變類型與不可變類型的變量分別做爲函數參數的區別# 感到疑惑能夠看以前的運算符擴展( http://www.javashuo.com/article/p-ftgdkctm-g.html)![]()
# Python中函數參數都是引用傳遞
# 對於不可變類型,因變量不能修改,因此運算不會影響到變量自身
# 而對於可變類型來講,函數體中的運算有可能會更改傳入的參數變量
# 函數名能不能重複的問題(能不能重載:具備不一樣的參數的類型或參數的個數【跟返回值不要緊】)
結論:函數名不能重名
來兩個有趣的擴展:1.交換兩個數熟悉吧,編程第一課,除了用第三變量 或者 兩數相加減 實現外,Python還有一種新方式:a,b=b,a
NetCore:這個我也是剛知道,O(∩_∩)O哈哈~還得謝謝評論區的兄弟^_^![]()
2.eval(和js裏面的eval差很少):不太建議使用![]()
[C#]C#時間日期操做
1、C# 日期格式
1. DateTime dt = DateTime.Now;
2. dt.ToString();//2005-11-5 13:21:25
3. dt.ToFileTime().ToString();//127756416859912816
4. dt.ToFileTimeUtc().ToString();//127756704859912816
5. dt.ToLocalTime().ToString();//2005-11-5 21:21:25
6. dt.ToLongDateString().ToString();//2005年11月5日
7. dt.ToLongTimeString().ToString();//13:21:25
8. dt.ToOADate().ToString();//38661.5565508218
9. dt.ToShortDateString().ToString();//2005-11-5
10. dt.ToShortTimeString().ToString();//13:21
11. dt.ToUniversalTime().ToString();//2005-11-5 5:21:25
12. dt.Year.ToString();//2005
13. dt.Date.ToString();//2005-11-5 0:00:00
14. dt.DayOfWeek.ToString();//Saturday
15. dt.DayOfYear.ToString();//309
16. dt.Hour.ToString();//13
17. dt.Millisecond.ToString();//441
18. dt.Minute.ToString();//30
19. dt.Month.ToString();//11
20. 22. dt.Second.ToString();//28
21. 23. dt.Ticks.ToString();//632667942284412864
22. 24. dt.TimeOfDay.ToString();//13:30:28.4412864
23. 25. dt.ToString();//2005-11-5 13:47:04
24. dt.AddYears(1).ToString();//2006-11-5 13:47:04
25. dt.AddDays(1.1).ToString();//2005-11-6 16:11:04
26. dt.AddHours(1.1).ToString();//2005-11-5 14:53:04
27. dt.AddMilliseconds(1.1).ToString();//2005-11-5 13:47:04
28. dt.AddMonths(1).ToString();//2005-12-5 13:47:04
29. dt.AddSeconds(1.1).ToString();//2005-11-5 13:47:05
30. dt.AddMinutes(1.1).ToString();//2005-11-5 13:48:10
31. dt.AddTicks(1000).ToString();//2005-11-5 13:47:04
32. dt.Add(?).ToString();//問號爲一個時間段
33. dt.Equals("2005-11-6 16:11:04").ToString();//False
34. dt.Equals(dt).ToString();//True
35. dt.GetHashCode().ToString();//1474088234
36. dt.GetType().ToString();//System.DateTime
37. dt.GetTypeCode().ToString();//DateTime
38.
39. dt.GetDateTimeFormats('s')[0].ToString();//2005-11-05T14:06:25
40. dt.GetDateTimeFormats('t')[0].ToString();//14:06
41. dt.GetDateTimeFormats('y')[0].ToString();//2005年11月
42. dt.GetDateTimeFormats('D')[0].ToString();//2005年11月5日
43. dt.GetDateTimeFormats('D')[1].ToString();//2005 11 05
44. dt.GetDateTimeFormats('D')[2].ToString();//星期六 2005 11 05
45. dt.GetDateTimeFormats('D')[3].ToString();//星期六2005年11月5日
46. dt.GetDateTimeFormats('M')[0].ToString();//11月5日
47. dt.GetDateTimeFormats('f')[0].ToString();//2005年11月5日14:06
48. dt.GetDateTimeFormats('g')[0].ToString();//2005-11-5 14:06
49. dt.GetDateTimeFormats('r')[0].ToString();//Sat, 05 Nov 2005 14:06:25 GMT
50.
51. string.Format("{0:d}",dt);//2005-11-5
52. string.Format("{0:D}",dt);//2005年11月5日
53. string.Format("{0:f}",dt);//2005年11月5日14:23
54. string.Format("{0:F}",dt);//2005年11月5日14:23:23
55. string.Format("{0:g}",dt);//2005-11-5 14:23
56. string.Format("{0:G}",dt);//2005-11-5 14:23:23
57. string.Format("{0:M}",dt);//11月5日
58. string.Format("{0:R}",dt);//Sat, 05 Nov 2005 14:23:23 GMT
59. string.Format("{0:s}",dt);//2005-11-05T14:23:23
60. string.Format("{0:t}",dt);//14:23
61. string.Format("{0:T}",dt);//14:23:23
62. string.Format("{0:u}",dt);//2005-11-05 14:23:23Z
63. string.Format("{0:U}",dt);//2005年11月5日6:23:23
64. string.Format("{0:Y}",dt);//2005年11月
65. string.Format("{0}",dt);//2005-11-5 14:23:23
66. string.Format("{0:yyyyMMddHHmmssffff}",dt);
2、日期格式模式 說明
d 月中的某一天。一位數的日期沒有前導零。
dd 月中的某一天。一位數的日期有一個前導零。
ddd 週中某天的縮寫名稱,在 AbbreviatedDayNames 中定義。
dddd 週中某天的完整名稱,在 DayNames 中定義。
M 月份數字。一位數的月份沒有前導零。
MM 月份數字。一位數的月份有一個前導零。
MMM 月份的縮寫名稱,在 AbbreviatedMonthNames 中定義。
MMMM 月份的完整名稱,在 MonthNames 中定義。
y 不包含紀元的年份。若是不包含紀元的年份小於 10,則顯示不具備前導零的年份。
yy 不包含紀元的年份。若是不包含紀元的年份小於 10,則顯示具備前導零的年份。
yyyy 包括紀元的四位數的年份。
gg 時期或紀元。若是要設置格式的日期不具備關聯的時期或紀元字符串,則忽略該模式。
h 12 小時制的小時。一位數的小時數沒有前導零。
hh 12 小時制的小時。一位數的小時數有前導零。
H 24 小時制的小時。一位數的小時數沒有前導零。
HH 24 小時制的小時。一位數的小時數有前導零。
m 分鐘。一位數的分鐘數沒有前導零。
mm 分鐘。一位數的分鐘數有一個前導零。
s 秒。一位數的秒數沒有前導零。
ss 秒。一位數的秒數有一個前導零。
f 秒的小數精度爲一位。其他數字被截斷。
ff 秒的小數精度爲兩位。其他數字被截斷。
fff 秒的小數精度爲三位。其他數字被截斷。
ffff 秒的小數精度爲四位。其他數字被截斷。
fffff 秒的小數精度爲五位。其他數字被截斷。
ffffff 秒的小數精度爲六位。其他數字被截斷。
fffffff 秒的小數精度爲七位。其他數字被截斷。
t 在 AMDesignator 或 PMDesignator 中定義的 AM/PM 指示項的第一個字符(若是存在)。
tt 在 AMDesignator 或 PMDesignator 中定義的 AM/PM 指示項(若是存在)。
z 時區偏移量(「+」或「-」後面僅跟小時)。一位數的小時數沒有前導零。例如,太平洋標準時間是「-8」。
zz 時區偏移量(「+」或「-」後面僅跟小時)。一位數的小時數有前導零。例如,太平洋標準時間是「-08」。
zzz 完整時區偏移量(「+」或「-」後面跟有小時和分鐘)。一位數的小時數和分鐘數有前導零。例如,太平洋標準時間是「-08:00」。
: 在 TimeSeparator 中定義的默認時間分隔符。
/ 在 DateSeparator 中定義的默認日期分隔符。
% c 其中 c 是格式模式(若是單獨使用)。若是格式模式與原義字符或其餘格式模式合併,則能夠省略「%」字符。
\ c 其中 c 是任意字符。照原義顯示字符。若要顯示反斜槓字符,請使用「\\」。
只有上面第二個表中列出的格式模式才能用於建立自定義模式;在第一個表中列出的標準格式字符不能用於建立自定義模式。
自定義模式的長度至少爲兩個字符;例如,
1. DateTime.ToString( "d"); // 返回 DateTime 值;「d」是標準短日期模式。
2. DateTime.ToString( "%d"); // 返回月中的某天;「%d」是自定義模式。
3. DateTime.ToString( "d "); // 返回後面跟有一個空白字符的月中的某天;「d」是自定義模式。
3、C# 經常使用日期處理函數
// 計算2個日期之間的天數差
1. DateTime dt1 = Convert.DateTime("2007-8-1");
2. DateTime dt2 = Convert.DateTime("2007-8-15");
3. TimeSpan span = dt2.Subtract(dt1);
4. int dayDiff = span.Days + 1;
// 計算某年某月的天數
1. int days = DateTime.DaysInMonth(2007, 8);
2. days = 31;
// 給日期增長一天、減小一天
1. DateTime dt =DateTime.Now;
2. dt.AddDays(1); //增長一天
3. dt.AddDays(-1);//減小一天
*注:如下的毫秒都採用最大997,而不是999 由於SQL SERVER的精度爲3毫秒
//本月的天數
int daysInMonth = DateTime.DaysInMonth(DateTime.Now.Year, DateTime.Now.Month);
//本年的天數 是不是閏年
int daysInYear = DateTime.IsLeapYear(DateTime.Now.Year) ? 366 : 365;
//本月第一天
DateTime firstDayInMonth = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
//本月的最後一天 本月1號加一個月得下月1號,再剪掉一天就是本月最後一天
DateTime lastDayInMonth = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1).AddMonths(1).AddDays(-1);
//本月最後一天的午夜
DateTime lastDayInMonth2 = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1).AddMonths(1).AddMilliseconds(-3);
//本年第一天
DateTime firstDayInYear = new DateTime(DateTime.Now.Year, 1, 1);
//本年最後一天
DateTime lastDayInYear = new DateTime(DateTime.Now.Year, 12, 31);
//本年最後一天的午夜
DateTime lastDayInYear2 = new DateTime(DateTime.Now.Year, 12, 31, 23, 59, 59, 997);
//獲得星期幾 星期天爲7
int dayOfWeek = Convert.ToInt32(DateTime.Now.DayOfWeek) < 1 ? 7 : Convert.ToInt32(DateTime.Now.DayOfWeek);
//本週一
DateTime monday = new DateTime(DateTime.Now.Year,DateTime.Now.Month,DateTime.Now.Day).AddDays(1 - dayOfWeek);
//本週 星期天
DateTime sunday = monday.AddDays(6);
//本週 星期天的午夜
DateTime sunday2 = monday.AddDays(7).AddMilliseconds(-3);
//本季度第一天
DateTime firsyDayInQuarter = new DateTime(DateTime.Now.Year, DateTime.Now.Month - (DateTime.Now.Month - 1) % 3, 1);
//本季度最後一天
DateTime lastDayInQuarter = firsyDayInQuarter.AddMonths(3).AddDays(-1);
//本季度最後一天的午夜
DateTime lastDayInQuarter2 = firsyDayInQuarter.AddMonths(3).AddMilliseconds(-3);
string datetime = "10-Jul-09";
string newdatetime = DateTime.Parse(datetime, new System.Globalization.CultureInfo("de-de")).ToString("yyyyMMdd");
4、C#比較兩時間大小
一、比較時間大小的實驗
string st1="12:13";
string st2="14:14";
DateTime dt1=Convert.ToDateTime(st1);
DateTime dt2=Convert.ToDateTime(st2);
DateTime dt3=DateTime.Now;
if(DateTime.Compare(dt1,dt2)>0)
msg.Text=st1+">"+st2;
else
msg.Text=st1+"<"+st2;
msg.Text+="\r\n"+dt1.ToString();
if(DateTime.Compare(dt1,dt3)>0)
msg.Text+="\r\n"+st1+">"+dt3.ToString();
else
msg.Text+="\r\n"+st1+"<"+dt3.ToString();
二、計算兩個時間差值的函數,返回時間差的絕對值:
private string DateDiff(DateTime DateTime1,DateTime DateTime2)
{
string dateDiff=null;
try
{
TimeSpan ts1=new TimeSpan(DateTime1.Ticks);
TimeSpan ts2=new TimeSpan(DateTime2.Ticks);
TimeSpan ts=ts1.Subtract(ts2).Duration();
dateDiff=ts.Days.ToString()+"天" +ts.Hours.ToString()+"小時"+ts.Minutes.ToString()+"分鐘" +ts.Seconds.ToString()+"秒";
}
catch
{
}
return dateDiff;
}
三、實現計算DateTime1-36天=DateTime2的功能
TimeSpan ts=new TimeSpan(40,0,0,0);
DateTime dt2=DateTime.Now.Subtract(ts);
msg.Text=DateTime.Now.ToString()+"-"+ts.Days.ToString()+"天\r\n"; msg.Text+=dt2.ToString();
[C#]C#中字符串的操做
1.Replace(替換字符):
public string Replace(char oldChar,char newChar);在對象中尋找oldChar,若是尋找到,就用newChar將oldChar替換掉。
如:
string st = "abcdef";
string newstring = st.Replace('a', 'x');
Console.WriteLine(newstring); //即:xbcdef
public string Replace(string oldString,string newString);在對象中尋找oldString,若是尋找到,就用newString將oldString替換掉。
如:
string st = "abcdef";
string newstring = st.Replace("abc", "xyz");
Console.WriteLine(newstring); //即:xyzdef
2.Remove(刪除字符):
public string Remove(int startIndex);從startIndex位置開始,刪除此位置後全部的字符(包括當前位置所指定的字符)。
如:
string st = "abcdef";
string newstring = st.Remove(4);
Console.WriteLine(newstring); //即:abcd
public string Remove(int startIndex,int count);從startIndex位置開始,刪除count個字符。
如:
string st = "abcdef";
string newstring = st.Remove(4,1);
Console.WriteLine(newstring); //即:abcdf
3.Substring(字符串提取):
public string Substring(int startIndex);從startIndex位置開始,提取此位置後全部的字符(包括當前位置所指定的字符)。
如:
string st = "abcdef";
string newstring = st.Substring(2);
Console.WriteLine(newstring); //即:cdef
public string Substring(int startIndex,int count);從startIndex位置開始,提取count個字符。
如:
string st = "abcdef";
string newstring = st.Substring(2,2);
Console.WriteLine(newstring); //即:cd
4.Trim(清空空格):
public string Trim ():將字符串對象包含的字符串兩邊的空格去掉後返回。
public string Trim ( params char[] trimChars ):今後實例的開始和末尾移除數組中指定的一組字符的全部匹配項。
如:
string st ="abcdef";
string newstring = st.Trim(new char[] {'a'});//尋找st字符串中開始與末尾是否有與'a'匹配,若有,將其移除。
Console.WriteLine(newstring); //即:bcdef
注:若是字符串爲"aaaabcdef",返回依然爲bcdef。當移除第一個a時,開始依然爲a,繼續移除,直到沒有。
public string TrimEnd ( params char[] trimChars ):對此實例末尾與指定字符進行匹配,true則移除
public string TrimStart ( params char[] trimChars ):對此實例開始與指定字符進行匹配,true則移除
5.ToLower(轉換大小寫)
public string ToLower():將字符串對象包含的字符串中的大寫所有轉換爲小寫。
6.IndexOf(獲取指定的字符串的開始索引)
public int IndexOf (sring field):在此實例中尋找field,若是尋找到,返回開始索引,反之,返回-1。
如:
string st = "abcdef";
int num=st.IndexOf("bcd");
Console.WriteLine(num); //即:1
7.Equals(是否相等)
public bool Equals (string value):比較調用方法的字符串對象包含字符串和參數給出的對象是否相同,如相同,就返回true,反之,返回false。
如: string a = "abcdef";
bool b = a.Equals("bcdef");
Console.WriteLine(b);//即:false
public bool Equals ( string value, StringComparison comparisonType ):比較調用方法的字符串對象包含字符串和參數給出的對象是否在不區分大小寫的狀況下相同,如相同,就返回true,反之,返回false,第二個參數將指定區域性、大小寫以及比較所用的排序規則.
如:
string a = "ABCDEF";
bool b = a.Equals("abcdef",StringComparison.CurrentCultureIgnoreCase);
Console.WriteLine(b);//即:true
8.Split(拆分)
public string[] Split ( params char[] separator ):根據separator 指定的沒有字符分隔此實例中子字符串成爲Unicode字符數組, separator能夠是不包含分隔符的空數組或空引用。
public string[] Split ( char[] separator, int count ):參數count 指定要返回的子字符串的最大數量。
如:
string st = "語文|數學|英語|物理";
string[] split = st.Split(new char[]{'|'},2);
for (int i = 0; i < split.Length; i++)
{
Console.WriteLine(split[i]);
}
注:count不填則所有拆分
public enum StringSplitOptions
成員名稱 說明
None 返回值包括含有空字符串的數組元素
RemoveEmptyEntries 返回值不包括含有空字符串的數組元素
如:
string st = "語文|數學||英語|物理";
string[] split = st.Split(new char[]{'|'},StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < split.Length; i++)
{
Console.WriteLine(split[i]);
}
將StringSplitOptions枚舉和Split()方法聯繫起來:
1. public string[] Split ( char[] separator, StringSplitOptions options ):options指定StringSplitOptions枚舉的RemoveEmptyEntries以省略返回的數組中的空數組元素,或指定StringSplitOptions枚舉的None以包含返回的數組中的空數組元
2. public string[] Split ( char[] separator, int count, StringSplitOptions options )
3. public string[] Split ( string[] separator, StringSplitOptions options )
4. public string[] Split ( string[] separator, int count, StringSplitOptions options )
9.Contains(判斷是否存在)
public bool Contains(string text):若是字符串中出現text,則返回true,反之false,若是text爲("")也返回true。
如:
string st="語文數學英語";
bool b=st.Contains("語文");
Console.WriteLine(b);//true
10.EndsWith,StartsWith(判斷字符串的開始或結束)
public bool EndsWith ( string value ):判斷對象包含字符串是否以value指定的字符串結束,是則爲 true;不然爲 false。
public bool EndsWith ( string value, StringComparison comparisonType ):第二個參數設置比較時區域、大小寫和排序規則。
public bool StartsWith ( string value ):判斷對象包含字符串是否以value指定的字符串開始,是則爲 true;不然爲 false。
public bool StartsWith ( string value, StringComparison comparisonType ) :第二個參數設置比較時區域、大小寫和排序規則。
如:
string st="語文數學英語abc";
bool b=st.EndsWith("英語ABC",StringComparison.CurrentCultureIgnoreCase);//第二個參數忽略大小比較。
Console.WriteLine(b);//true
11.Insert(字符串插入)
public string Insert ( int startIndex, string value ):在指定的字符串下標爲startIndex前插入字符串value。返回插入後的值。
如:
string st="語文數學英語abc";
string newst=st.Insert(6,"物理");//注:在指定索引「前」插入。
Console.WriteLine(newst);//即:語文數學英語物理abc
[ASP.NET]NTKO插件使用常見問題
1、環境要求
NTKO OFFICE文檔控件可以在IE、谷歌Chrome、Firefox等瀏覽器中直接編輯MS Office、WPS、金山電子錶、永中Office等文檔並保存到WEB服務器。(標準版對IE瀏覽器的兼容進行了驗證,其餘瀏覽器並未驗證)
使用Ntkooffice套打,對配置環境要求較高,以MS office爲例,須要安裝完整版Office。
備註:文檔控件是ActiveX控件,經過瀏覽器操做本地的office,因此說系統用戶的權限必須管理員身份,這樣控件才能正常的加載;還有就是訪問的系統裏面有文檔控件,必須將這個系統加入到IE的可信任站點中去;
加入可信站點如圖:IE工具欄-Internet選項
這保護模式不要啓用;
這https驗證取消,而後點擊添加就好了;
若是在使用文檔控件,在office文檔和表單中的附件一併保存的時候出現失敗;
檢查一下IE安全設置,將「將文件上載到服務器時包含了本地目錄路徑」 啓用 如圖:
二、常見錯誤
2.1 問題:彈出下圖「對象不支持」提示
解決方法:第一次運行時須要容許加載項,而後刷新後從新打開打印頁面。
2.2 問題:NTKO OFFICE文檔控件不能自動裝載
緣由分析:控件不能自動加載主要有如下緣由致使
1)本地Internet選項中的安全設定,在當前區域禁止下載已簽名的ActiveX控件;
2)引用控件的網頁中,<object 標記中的codebase屬性指定不正確,致使瀏覽器沒法下載OfficeControl.cab文件;
3)服務器上的OfficeControl.cab被破壞,失去正確的簽名,或者使用了不正確的版本;
4)雖然服務器上的OfficeControl.cab正確,可是瀏覽器下載的有問題。這個可能會由於某些WEB服務器的mime的錯誤配置引發,致使服務器將OfficeControl.cab不以二進制文件的形式發送給瀏覽器;
5)本地Internet選項中的安全設定,在當前區域不容許運行ActiveX控件和插件;
6)還有多是因爲微軟的補丁引發,或者其餘防病毒軟件或者過濾軟件阻止了控件安裝;
解決方法:
1) 確認本地Internet選項中的安全設定中,容許下載已簽名的ActiveX控件,並容許運行ActiveX控件和插件。
2)確認引用控件的網頁中,<object 標記中的codebase=部分,正確指向了服務器上的OfficeControl.cab文件的URL[相對當前網頁或者相對服務器根]。
3)從瀏覽器地址欄直接輸入服務器上的OfficeControl.cab文件的URL,包含主機名,確認瀏覽器出現下載提示而且在下載保存後的OfficeControl.cab文件上,點擊右鍵看屬性,在出現的對話框中具備「數字簽名」,且簽名正確。
4)若是以上方法還不能解決問題,而且您的系統安裝了「微軟累積安全更新 MS05-052補丁」,請嘗試以下步驟:
警告:若是使用註冊表編輯器或其餘方法錯誤地修改了註冊表,則可能致使嚴重問題。這些問題可能須要從新安裝操做系統才能解決。
一、單擊「開始」,單擊「運行」,鍵入 Regedit.exe,而後單擊「肯定」。
二、找到如下注冊表子項:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\ActiveX Compatibility
三、右鍵單擊「ActiveX Compatibility」,查找NTKO OFFICE文檔控件的CLSID:{C9BC4DFF-4248-4a3c-8A49-63A7D317F404},若是該項目存在,右鍵單擊右邊的「Compatibility Flags」項目,而後單擊「修改」。在「數值數據」框中,選擇16進制,輸入00800000,而後單擊「肯定」。
四、若是該NTKO OFFICE文檔控件的CLSID不存在,則右鍵單擊「ActiveX Compatibility」,指向「新建」,單擊「項」,鍵入NTKO OFFICE文檔控件的CLSID:{C9BC4DFF-4248-4a3c-8A49-63A7D317F404},而後按 Enter。
五、右鍵單擊您在步驟 4 中建立的項,指向「新建」,而後單擊「DWORD 值」。
六、鍵入 Compatibility Flags,而後按 Enter。
七、右鍵單擊「Compatibility Flags」,而後單擊「修改」。
八、在「數值數據」框中,選擇16進制,輸入00800000,而後單擊「肯定」。
九、退出註冊表編輯器。
5)若是以上方法還不能解決問題,嘗試暫時關閉防病毒軟件或者其餘過濾軟件再進行安裝。
6)若是仍是不能解決問題,多是機器配置被破壞,能夠嘗試進行手工安裝。具體請參考相關文檔。
2.3 問題:加載文檔時出現「下載文檔數據失敗」對話框
解決方法:
錯誤緣由是後臺url數據錯誤。能夠嘗試從瀏覽器打開url,若是是後臺錯誤,能夠看到詳細的錯誤信息。若是瀏覽器能夠打開,控件不能打開,則能夠試試設定控件屬性<param name=」IsUseUTF8URL」 value=」-1」>
2.4 問題:加載文檔時出現「您沒有正確安裝OFFICE,或者請求建立一個系統不支持的OLE文檔類型」錯誤
解決方法:
這個錯誤是由於接口沒有註冊。跟控件自己無關。能夠嘗試一、打開windows的「寫字板」應用程序,選擇插入word文檔對象。若是這個出錯,能夠肯定是office安裝問題,或者是由於ole32.dll沒有註冊。二、能夠嘗試在命令行運行「regsvr32.dll」,再試試。三、若是不行,能夠完全卸載office,從新安裝。
2.5 問題:控件爲何有時加載文檔顯示空白,有時可正常加載
這個多是在body中直接調用OpenFromUrl/BeginOpenFromUrl,但此時控件並未徹底初始化/加載完畢,因此出現空白。解決:能夠在<body onload=」…」>中調用js函數,這樣能夠確保在瀏覽器加載控件完畢以後,纔在該js函數中調用OpenFromUrl/BeginOpenFromUrl,這樣就能夠解決了
2.6 問題:文件存取錯誤
解決方法:
首先按照備註操做,將系統加入到IE的可信站點中去;若是加入了可信站點仍是報文件存取錯誤的話那就是本機office的問題了,本機office是精簡版的office,卸載了本機的而後重裝一個完整的office;
1.環境問題,按照如下步驟檢查
1)在寫字板插入word對象試試,若是不報錯,說明office是正確安裝的
2)打開命令行,而後輸入regsvr32 ole32.dll (win7須要這樣打開:全部程序 附件 命令行#鼠標右鍵以管理員身份執行)
3)若是1)2)都沒有問題,能夠打開任務管理器看看是否有未結束的WINWORD.EXE EXCEL.EXE進程,關閉試試
4)刪除normal.dot normal.dotx試試,這兩個文件是office的模板文件,在目錄C:\Documents and Settings\當前用戶\Application Data\Microsoft\Templates下
5)windows7還能夠嘗試把OA或系統的IP加入信任站點,取消保護模式試試
6)若是以上方法都不行,請從新安裝office試試(推薦徹底安裝)
只有部分文檔打開時報錯
2.文檔被損壞
1)因爲未知緣由,文檔被損壞,這時,能夠把從本地打開這個文檔,另存一份出來試試控件是否能打開
2.7 問題:使用文檔控件打開服務器上面的文檔時,出現文件傳輸錯誤
解決方法:
控件對象.openFromUrl(url);參數url必須可以返回標準文檔的二進制數據流。它能夠直接指向服務器上的一個word文檔或者頁面(這個頁面讀取文檔的數據流,並返回給客戶端)。
出現錯誤分爲下面幾種狀況:
1:url錯誤。若是url沒有問題在瀏覽器的地址欄直接輸入url對應的全url應該可以下載word文檔。若是url有問題,控件沒法獲取文檔數據,就會提示「文件傳輸錯誤」。
2:編碼問題。好比url中帶有中文字符,瀏覽器對url編碼導至url被破壞。服務器根據被破壞的url固然也不能返回正確的word二進制流。能夠經過設置控件的isuseutf8url=-1(即便用utf8對url編碼)。有的時候即便設置了isuseutf8url=-1也不能解決問題。根據經驗,能夠調用url=escape(url);來從新對url編碼一次,而後再調用openFromUrl(url)。
3:服務器設置自己就不支持中文的url。好比tomcat服務器,是能夠經過服務器配置文件來設置url編碼,有的編碼格式原本就不支持中文。這種狀況就須要從新設置可以支持中文的url編碼格式。
保存文檔回服務器時報「文件傳輸錯誤」 |
2.8 問題:控件使用一段時間後忽然提示"您正在運行的NTKO OFFICE文檔控件是演示版本已經到期,不能繼續使用。(.net版本)
解決方法:
到標準版部署包中拷貝下圖的3個文件 ,覆蓋項目組對應路徑下的文件。
2.9 問題:檢測其餘地方沒有任何問題就是文檔保存的時候出現不知名錯誤
解決方法:
可能引發的緣由就是在:打開文檔Openfromurl第二個參數或者BeginOpenfromURL第三個只讀屬性設置爲true,這樣就不能將文檔保存回服務器;因此解決方案就是將這個參數設置爲false就能夠解決;
2.10 問題:當客戶端的office版本含有200三、2007和2010,保存文檔的時候怎樣處理兼容問題
解決方法:
由於低版本的office不能兼容高版本的office文檔格式(如office2003不能打開07和10文檔),因此建議在保存文檔時候可使用SaveAsOtherFormatToURL方法,該方法用來將文檔保存爲其餘格式的文件到指定的URL。除第一個參數以外,其餘參數的格式以及返回值,和SaveToURL方法的參數一致。
第一個參數指明要保存的文件類型:
對Word文檔而言,第一個參數的含義以下:
0:保存爲word Txt格式;
1:保存爲MHT格式。須要客戶機安裝OFFICE XP及以上版本;
2:保存爲XML格式。須要客戶機安裝OFFICE 2003及以上版本;
3:保存爲RTF格式;
4:保存爲UnicodeText格式;
5:保存爲兼容WORD文檔格式;
對Excel文檔而言,第一個參數的含義以下:
0:保存爲Txt格式;
1:保存爲MHT格式。須要客戶機安裝OFFICE XP及以上版本;
2:保存爲XML格式。須要客戶機安裝OFFICE 2003及以上版本;
3:保存爲CSV格式;
4:保存爲UnicodeText格式;
5:保存爲Excel7格式;
7:保存爲Excel95格式;
對PowerPoint文檔而言,第一個參數的含義以下:
0:保存爲GIF格式;
1:保存爲MHT格式。須要客戶機安裝OFFICE XP及以上版本;
2:保存爲JPG格式。
3:保存爲RTF格式;
4:保存爲PNG格式;
三、其餘
3.1 問題:頁面分辨率問題
大屏顯示器可能會存在頁面顯示不美觀的問題
解決方法:須要使用大屏顯示的項目組能夠個性化調整頁面。
3.2 問題:附件誤刪問題
假如已經打開證照而且編輯進行了保存操做,則會在框架目錄下的對應文件夾下生成一個附件實例,這個時候若是誤刪實例,則會出現圖2的錯誤。
EpointFrame\BigFileUpLoadStorage\2017\1\EpointFrame
圖1:
圖2:
3.3 問題:瀏覽器兼容性問題
標準版對IE及360瀏覽器作了兼容性驗證:
兼容IE 不兼容360
對官網宣傳的谷歌Chrome、Firefox瀏覽器未進行驗證。
我對C#的認知。
關於開發者的技術水平到底該如何定義,到底一我的的技術水平應該定位在高、中、低的標準是什麼呢?不少人以爲這是一個仁者見仁的問題,有人以爲根據公司的那個員工等級判斷。答案是確定不是,從純開發技術的角度來分析。不少人以爲本身一門語言精通了就去學其餘語言了,美其名曰集大成者,這樣的工做十幾年倒是初級水平的技術人員也很多。
下面我來說講個人認知,C#這門技術到底學到什麼程度能夠進入到什麼級別。
我常說C#的入門技術是委託、事件、消息。只有當你能夠純熟運用這三個技能的時候,纔剛剛入門,此時C#的大門纔算正式爲你打開。不少人在學了一些語法編寫一些項目後就以爲C#精通了,其實大家還沒入門呢(對日開發的居多)
下面上一個圖片,你們來看看本身的定位,固然是純技術角度,其實,有些時候一個軟件架構,用初級軟件工程師也是能夠架構的。
1, comom language runtime :初級人員無視他,中級人員起碼要知道他,高級人員多數要會使用其中一些應用好比security,架構師要理解原理。
2, .netframework :這裏有許多框架,會的越多越好。
3, Base class library :這裏都是基本語法你會了多少呢,想成爲高手必定要所有學會,一個都不能丟。
4, Runtime infrastructure library:這裏內容初級開發者不用瞭解,進入中級就要開始一點點吸取了,想到高級要所有消化,是所有哦。
5, Framework calss library:這裏都是基本應用,初級程序員肯能都會接觸一些,中級就會了解和運用一些,高級就要所有會用。
6, Core concepts:這裏的內容同上。
7, Core features,core objects,CLI language,DLR略過。。。
8, Desktop:CUI瞭解就行,GUI要深刻了解,另外這裏的涉及到了XAML語言,這個要學會。
9, Web:這裏涉及的框架sharpoint若是工做沒涉及不去了解也是能夠的,但asp.net是必會的,其中的MVC就算工做沒應用也要學會。Asp.net runtime是進階高手的一個路障,瞭解的越多越好。Silverlight的話,會xaml基本就能用,若是工做須要精通。
10, SOA:這也是個必會的東西,並且至少要精一個。
11, Open web interface for .net:要了解,會使用,若是工做須要,要精通。
12, SDK:要了解,會基本使用。
13, Development:這個基本沒有人能全會,但工具這個要熟練使用,畢竟工具會的越多越好,但不是技術加分。
14, Platforms:這個基本很難有人全精,但多少要了解,工做用過的要精通。
15, Productivity:起碼nuget要會用。
16, Build:高級人員要了解原理。
17, Testing:至少要會使用1個,其餘的要了解。
18, Deploy/publish:這個基本都百度的出用法,瞭解就能夠,起碼知道有這個東西,須要的時候能夠百度。
19, Framework tool:這裏有些是必會的,有些會用就行,但最好所有了解,須要的時候學習用法。
20, Data:這裏內容做爲高級人員是必會的,若是其中的orm能夠用EF做爲跳板深刻研究(這裏的水很深)。
21, Conponents:中級之後不免要接觸這些,瞭解的越多進步的越多。
22, Concept:這是圖片裏沒有的,中級之後就會接觸的,像什麼IOC,AOP,MVC,MVVM,DDD等等,在學習這些的過程當中能夠逐漸向架構師前進,其實這些概念學會了以後會發現,概念只是裝逼用的。在概念裏分爲基本概念和高級概念,像IOC,AOP就是基本概念,這些東西在編碼時你已經應用過了,並且有一些現成的開源代碼,並且原理很簡單,學會後能夠用具體語言來把你編碼的方式表達出來,不去了解也無妨,但知道的多了,方便忽悠;而DDD就是高級概念,光百度是學不會的,必定要應用過才能瞭解,但DDD這樣的高級概念很複雜,非技術人員很難理解,技術人員也未必有那麼好的口才講解,而IOC,AOP這類的簡單概念很容易理解,基本上口才笨拙的開發人員也能講的很溜,很適合給領導很講解。因此在領導看來,會基礎概念和會高級概念都是同樣同樣同樣地。
看到這裏是否是那些覺得C#很簡單的同窗就很吃驚啦啊,那些自覺得本身是大神的是否是發現,原來本身不過纔是剛入門的小菜鳥啦,那些覺得本身C#精通的外包達人們,是否是打開圖片後一臉陌生的感受呀。其實,C#並不比其餘語言簡單,水深的狠,哪那麼容易精通。
這些還只是C#,做爲一個程序員,還要有其餘必備的知識,好比HTML和CSS你得會,JS你得會,別說你知道標籤是什麼意思就說本身會了,起碼DIV+CSS切圖玩的起來纔算會。數據庫你得會,數據庫水很深,別輕易說本身有初級DBA的水平,那些傳說中天天備份表數據的初級DBA但是連入門都沒有呢,不要和他們比;做爲高級開發人員,起碼存儲過程要信手拈來把,起碼要有解決過大數據死鎖的經驗吧。若是業餘愛好再豐富一點的人,PS基本使用也要會把,falsh也要了解吧,3Dmax是否是也能夠玩玩啊,程序員也要有美感嘛。此外,程序員要會寫文檔,解決方案但是基本技能,高級點的概要設計也是文檔嘛。另外高級程序員不免還得寫點ppt吧。
除了這些,還有一些要了解的東西,好比操做系統呀,硬件呀,軟件工具等等,由於不必定何時你面對着一些性能bug,就須要他們的知識才能解決,或者解釋。
再更上一層樓,要接觸一些開源代碼啦,如今Xamarin都開源了,你有去了解嗎?不少開源代碼都很厲害的,不要對我說在CSDN下載了一些開源代碼啊。。。
【PS:若是有須要購買Xamarin安卓框架的能夠聯繫我,分爲原始框架和web嵌入框架兩種,後者採用angularjs+web api技術,Web頁面端實現MVVM :)】
以上所有是純技術分析,固然不是所有,若有遺漏歡迎你們補充。
上面這些都是純技術,是虛擬社會,回到現實世界,因爲一些人是由初級程序員,尤甚者未入門的程序員,直接跳級到了架構師,或者高級程序員,從而引起代碼世界的混亂,而這樣的人才之因此成功,除了自身年齡和口才外,和那些非技術人才的力捧也是主因之一。不過呢,話說回來,咱們是商業社會,有些項目能用便可,有些項目拖延到爛尾也是必要的,因此口才的重要性,並不比技術低。一個技術沒入門的架構師並不比一個真才實學的架構差,即使他們其餘技能也是零,由於我相信存在便是合理。