|
|
|
17:20 |
|
|
transcript
|
2:33 |
Hello, and welcome to Python for the .NET Developer. I'm so glad you're here in this course and that you're excited about learning Python well, as a .NET developer. In this set of videos, we're going to talk about what you're going to learn, what prerequisites you need and why Python is such an amazing language. Let's begin with the methodology of this course. Sure, you could just go take some random Python course. Heck, we have many random Python courses some of them are getting started courses. Knowing that you're a .NET developer we want to make that jump from C# to Python much cleaner, much more reliable and more comfortable. So what we're going to do is we're going to take all the stuff that you love about C#, .NET and its ecosystem, ASP.NET, Entity Framework, Linq Lambda Expressions, classes, generators, whatever it is. The stuff that you love in C# we're going to look at it first in C# in working examples, and then for that example we're going to rebuild it from scratch in Python. Are you a fan of ASP.NET? Cool, over in Python we have something called Flask and it works a lot like that. So we're going to build a cool web app in ASP.NET and then we're going to rebuild that app in Python. Do you think Lambda Expressions are all the rage and make your C# code so much better to read and write? Well, in Python we have something similar and we're going to create some little examples in C# with Lambda Expressions and then rewrite those in Python. Working with databases just is not going to be the same once you get started with an ORM. Entity Framework is the ORM for C# and .NET. Over in Python we have amazing ORMs, as well and they work very similarly to Entity Framework. So we're going to take a data driven app in C# and we're going to, you guessed it, rebuild that app in Python. So the idea, the methodology of this course is we're going to take everything you love about C# and .NET and we're going to show you the Python equivalent talk about how we put it together how we decided which aspect of Python to use or which library to use to implement that. Instead of going, Well, I'm going to jump into Python and I'm going to be a total newbie I'm not going to know how to do anything you're going to jump into Python, have all of your experience in C#, I know how to do data bases, I know how to do web apps, I know how to do X, Y and Z," well, guess what? We're going to show you how to do all that stuff in a super smooth way over here in Python so you can jump in and be productive immediately.
|
|
|
transcript
|
3:04 |
As a .NET developer, you could go learn many other languages. C# requires a lot of skill and it's similar to many other languages as well. JavaScript might be a good choice. C++, maybe that's a good choice or even gasp, Java. You could go learn that as well. So why should you learn Python? Well, let's start with a story originating from a place that I'm sure you're familiar with Stack Overflow. Stack Overflow was created by Jeff Atwood and Joel Spolsky who had a lot to do with the Microsoft space. So kind of the home of .NET Q&A in the early days, right? Well, they wrote this cool blog post, The Incredible Growth of Python. So they went through and they analyzed all the questions on Stack Overflow and they said, Which ones are tagged with Python relative to other languages? Let's look at that over time. Let's look at how that's growing. Let's do some data science and predictive analysis and see what we can find out about the Python space relative to other things. Here's the first graph that they presented. They said, We're going to focus on high-income countries, and they plotted out the interest in questions for any given language over time. Do any of these stand out to you? Do any look particularly amazing versus, you know ones that are downward-trending like PHP? PHP is not a good thing to learn right now because it's just fading. Java's pretty flat. C# went down from its original high but then it flattened out. But certainly the last two years it's either a flat or slightly downward, which is not amazing. On the other hand, Python is unlike all of these languages. It's growing so incredibly quickly. I don't know about you but if I was going to position my career to glide along one of these curves would you want a downward curve or would you want something that is rocketing up? Well, maybe Python was popular. Maybe this is true of this graph but say that little peak at the top? Maybe that's like a super-turn and like we're all going back down and it was just a blip on the radar. Well, these folks did some analysis to figure out where they think it's going to be in a couple years. Look at this. It was impressive before. It's ridiculous now. So you can see this is the future traffic predicted with the STL model along with a 80% prediction interval. Python is really good to learn right now. And on one hand, it doesn't matter how popular a language is if you're just trying to build an app. On the other hand, it really actually honestly does. It means there are many more libraries available. Those libraries get more attention. It means there's more tutorials. And it also correlates with career and job growth. So Python is an amazing language to learn right now. As a C# developer, once you get over the initial shock of Oh my gosh, here's the language that's different I think you'll find it is a super, super-language. It really pairs up well with the stuff that you already know and love and that's what this course is all about, making those connections for you.
|
|
|
transcript
|
0:36 |
I'm sure you're wondering what experience do you need in order to take this class? What knowledge do we assume that you already have? Well, not too much. We think that you know C# and that you're familiar with .NET the runtime, and the base class libraries. That's about it. As long as you know the basics of the C# language and you're roughly familiar with some of the things in .NET like Entity Framework and ASP.NET this course will be custom-tailored for you because, like I said in the beginning we're going to take those concepts see some application using them and then rebuild Python's version of that.
|
|
|
transcript
|
3:37 |
This course is going to be full of hands on examples using awesome Python technologies libraries, language features and so on. So let's quickly talk about what you'll learn. First thing that we're going to do we're going to spend a fair amount of time on is just the Python language itself. But, like C#, the Python language is just the tip of the iceberg. There's an entire standard library what Python calls their Base Class Library from .NET as well as many, many, many external libraries that we can bring in and use to build amazing applications. But first, we're going to focus on a solid foundation with the Python language and we're going to be using an editor called PyCharm. This is by the same company that creates things like Resharper that plugs into Visual Studio and makes it awesome. Use a whole IDE specifically built to make writing Python code amazing. After that, we're going to focus on object oriented programming. Python has amazing object oriented programming features and we're going to do a whole chapter on that. As I hinted with my many, many, many packages yes, there are many packages in the package management framework or location that puts these all together and lets us install packages that extend our Python application, called the Python Package Index often referred to as PyPI for short. We're going to see how we can use PyPI to manage packages in our application and how those packages make our application do amazing things in just a couple lines of code. Having a good understanding of how your application runs requires a good understanding of how your code in general is run on that platform. Then, we're going to spend a whole chapter thinking about Python's memory management and how it manages memory for you and what that means for runtime consideration. So, we're going to dig into Python's memory management. After that, it's time to start building rich applications. So, we're going to build an awesome web application with Flask, this is like ASP.NET NVC but for the Python world. And, of course, web apps require database access. In .NET we have Entity Framework in Python we have SQLAlchemy along with a handful of other amazing ORMS. So, we're going to use SQLAlchemy to build a database backend for our web app. Of course we want our code tested we want it to be reliable, don't we? So, we're going to use the application library called pytest that lets us write unitests in a really clean and factored way. If you want to get a lot done, sometimes that requires parallelism, so we're going to explore the async and await keyword. No, not in C#, maybe a little bit but we're going to explore in Python because Python also has the async and await keywords and Asyncronous methods that are going to be super familiar to you as a .NET developer. What might not be so familiar what might be new, and is really amazing is something called Jupyter. Jupyter Notebooks and Jupyter Lab. These are computational notebooks that are very different from traditional applications you would write. They execute piece by piece with lots of visualization and exploration, so we're going to go explore two different types of data using Jupyter Jupyter Notebooks, and Jupyter Lab. Then, we're going to round out the course by taking our data driven web app that we built in Flask and deploying it on Linux, in the cloud. So, we're going to work with Ubuntu with uWSGI and Nginx to properly deploy our app. So, it performs amazingly on a super cheap virtual machine in the cloud. That's it. Of course, we're covering more there's many little things that we're touching on but here's the big summary of the topics we're going to cover. Think of all the things that you could do with all this technology after you've taken this course. You're going to be on fire.
|
|
|
transcript
|
4:08 |
Being new to the Python space, you might wonder what can you build with Python? What apps are out there that you know of that are actually built with Python? Maybe you don't know they're built with Python but yes, in fact, they are. So in this short section I just want to give you a taste of what is out there and what is built with Python so you can think of it and reference what you want to build and things that you're trying to do. When I think of companies that are impressive to me these days well Space X is absolutely among them. What Elon Musk, and his team over there are doing to jump ahead of all these governments and just create true innovation in space. It's blowing my mind, it's like we live in the future. And guess what? If you go over there, there are 92 different job positions probably more jobs than that open for Python developers at Space X. They don't talk about exactly how they're using it but I know that they're doing some amazing stuff there. Spotify. Spotify makes heavy use of Python for their web apps and APIs. NASA. NASA uses Python for a lot of things. They did this montage of how we're going to reach the moon this new project that they're on. And they had all these different people and engineers and they had one section where they were focusing on a awesome code that they were writing. Yeah, that was Python code. Bitly, the URL shortening service. Bit Bucket. JP Morgan Chase. Some of these, Spotify, Bit Bucket they got those like little start-ups and that there kind of thing. But enterprise stuff, what about that? Well, JP Morgan Chase, they're core trading engine the central part of their bank is built in Python. In fact, 35 million lines of Python code that JP Morgan Chase has doing super central stuff over there. Quora, Q&A site I love how rich and detailed the answers are over at Quora. That site, you guessed it, Python. Disqus the way you can plug in the comments at the bottom of your blog or other webpages. They talk a lot about how thy use Python and how they scale it. Really amazing. Instagram. Instagram does all sorts of stuff with their APIs and their web apps in Python. They gave an amazing keynote at PyCon a couple years ago about what they're doing with Django and it's super impressive. Read It. Front page of the internet, as they say sometimes. Read It is not only built in Python but there's an archival version of it where you can get the source code for the Read It site and yeah they use tons of the technology that we're covering in this course. YouTube. YouTube is built in Python and they get millions of requests per second. Per second. And it's built in Python, doing amazing stuff. There's a mix to technologies over there but Python's central over at YouTube. PyPI, the Python packaging index is implemented in. No surprise really there, Python. Pintrest. Pintrest is also Python and Django. PayPal. PayPal has some central APIs that do their pricing their real-time pricing stuff and these APIs get called billions of times a day. They need super, super low latency response times You know like, five milliseconds, that's a lot can we get that down to three type of response time. Python. Dropbox is almost entirely Python. Both the stuff behind the scenes, as well as the client the little box icon that appears in your task bar or your menu bar, all that is Python. They have millions of lines of Python making Dropbox possible. And finally, last but not least yeah, Talk Python. The training site, our APIs, so much of what we do of course is built in Python and it's been serving us incredibly well and it's going to continue I'm sure. Here are just some of the things that are built with or using Python deeply. These are amazing, right? If it worked for them chances are Python's going to work awesome for you too. There's a quick little link here at the bottom. This links over to the description of many of these different companies how they're using Python, and so on. Not all of them, like Space X and JP Morgan they're not covered there. Well, neither is Talk Python I guess. But a lot of the other stuff covered here they actually talked specifically about how they're using Python if you want to dig deeper and see what's going on.
|
|
|
transcript
|
0:28 |
I want to tell you, don't worry. More than half of this course way more than half of this entire course, 10 and 1/2 hours is building hands-on code with an editor either Visual Studio or PyCharm. So we're going to be building tons of code in here and this is just a call to say we're going to set the stage do just a little bit of high-level overview before we dig into writing the code. Hang tight, let us get everything lined up just right for you and we're going to start writing that Python code.
|
|
|
transcript
|
2:54 |
You might be wondering Who is that disembodied voice telling you all about Python? Well, hey, it's me, Michael Kennedy, nice to meet you. I'm so glad you're taking my course. Follow me over on twitter @mkennedy. Now, what have I been doing the Python space that makes it worth listening to me? I happen to run the most popular Python podcast out there called Talk Python To Me. I've been running this for about four years and many of the technologies we're covering in this course I've sat down and had deep conversations with the founders and the people maintaining these projects about where they came from why they built it the way they did, and where they're going. So I've spent a lot of time talking to the folks who build Python for us. I also run the Python Bytes Podcast along with my co-host Brian Okken. This is like a news show for the Python space that we do an episode every week. You can bet I'm on top of all the Python trends. And finally, I'm the founder and principal author at Talk Python Training, where you're taking this course. You can probably tell, I'm pretty excited about Python and I am very excited to tell you about it. But there's one more question you might want answered for this particular course. Why should I be qualified to tell you about C#? Yeah, I'm some Python guy, right? Well, yes, but I was also head of the curriculum and an instructor and author at DevelopMentor one of the main training places where people learned .NET in the early days. I worked with some of the thought leaders in the .NET space when .NET was originally released. Also spoken at international conferences NDC Oslo, Dev Week in London, a bunch of other conferences about .NET to .NET developers. I've written some articles that were published in MSDN Magazine. Can you see the by in this one? ASP.NET long-running workflows by Michael Kennedy. In fact, I still get invites to go to the Microsoft conferences from Microsoft. In just a few weeks, I'm going to Ignite to be part of their special podcasting event. Last couple of builds I've been there on their invitation. I'm very connected to the .NET and Microsoft space. Absolutely my history and, even still, in some ways. Why am I telling you this? Not because I want to make myself sound important. Actually, I don't really like talking about it like this. But, I want to point out that I have been one of you. I have been in the C# space, I wrote professional C# for over ten years. I think C# is a great language and I really enjoy working in the .NET Framework. Being a Python developer but also someone with a rich .NET history, I think I'm uniquely positioned to line up the dots for you, to say Here's what you do in C#, here's how you do it in Python. Here's what you do in C#, here are the three ways to do it in Python and here's why you pick those and so on. We're going to have a ton of fun digging into C# and seeing how to replicate all of those ideas over in the Python world. I'm going to make a prediction. By the end of this course, you're going to love working with Python.
|
|
|
|
7:53 |
|
|
transcript
|
2:45 |
In this short chapter we're just going to talk about the setup and tools that you need in order to follow along and work on the code from this course. Would it surprise you to hear that you need Python? Yeah, that's right you're going to have to have Python installed for our Python course. But, specifically, you're going to have to have at least Python 3.6 or higher. Look, if 3.9 is out, go get that. At the time of this recording they just released 3.8 so that's totally good. In particular we're going to need to use the async and await features that were introduced in Python 3.5. Throughout the course we use what are called f-strings in Python. These are formatted strings. Think string interpolation the dollar sign string in C#. That requires 3.6 or above. So, basically, to run the sample code exactly as it is you're going to need 3.6 or above but like I said, get the latest. You may be wondering, do I already have Python? What version is it? Do I need to update it? Some operating systems come with it. Others don't. So if you're on macOS or Linux, you can type Python3 -V and it'll print out the version. Like I said, 3.8 just came out but it hasn't gotten a chance to propagate over to my MacBook yet. 3.7.4 is what we got installed right now. And this is plenty good. 3.7 is great. This is how you check on Mac and Linux. Most of you, I would suspect, are on Windows. And on Windows, if you type Python -V, capital V again you'll see what version of Python you have there. But there's a caveat. Python in Windows is a little bit tricky. Until very recently they didn't have this Python3 command that lets you -V, a command, distinguish between Python 3 and Python 2 or whatever the default version is. Depending on how you have Python installed on Windows this might report the latest version of the most up-to-date version of Python or it might just report the version that is the latest or the most recent in the path okay, that occurs earliest in your path on Windows. So you can type where Python. It'll give you a long list of all of the options that you could possibly run and then you might see oh, here's a newer version. Let me make sure that that's listed in the path first. Both platforms we're going to need 3.6 or higher. Here's how you check. One final note on Windows. If this comes up with something weird or doesn't give you an output like if it doesn't say Python something below just type Python alone and that will probably on the latest version of Windows 10 open up the Windows store and suggest that you go get and install Python 3 from the Windows store. So there's this command on Windows that is Python even if you don't have Python installed. It's just a shim to launch the store app version of Python and get that set up for you. Okay?
|
|
|
transcript
|
0:37 |
Now, if you do need to install Python if you don't have it yet, you can just go to Python.org and download it, and install it, that's probably fine. But there's actually a ton of different ways to get Python on your system, and they have trade-offs and they have different update paths and all of that so it might be worth dropping over on the Real Python article, Installing Python. realPython.com is a great place that has all sorts of tutorials and other information about Python. I'm sure as you're going through this journey you'll be there a lot, but they have this cool article about installing Python on the different operating systems so if you need to install Python, have a look here.
|
|
|
transcript
|
2:09 |
We're going to need a proper editor to work on our code. We're going to write a bunch of cool apps we're going to write some database apps going to write some data science apps web apps, all kinds of things. A really super simple, simplistic editor would suffice but it is really not what we want. So there's a couple of choices we could choose but I'm going to be using PyCharm for this course. I do believe it is the best way to write Python code and I think as a .NET developer you're going to really, really appreciate it. For the .NET side of the world Microsoft side of the world I do want to throw out that the second best editor in my opinion that is right behind PyCharm is VS Code with the Python plugin. So if you want to use that that's totally fine. But we're going to be using PyCharm. There's a Community edition and then there's a paid edition. The Pro edition, the paid edition is what we're going to need to do some of the data science and the web work, the database work. But other than that you could use the Community edition of PyCharm for everything else. I'm tempted to go into all the details about why this is so awesome. Do want to say that we will go through lots of the features and you'll see this thing in action over and over and over. We're going to write a ton of code throughout this course so you're going to get to learn how to use it really well. But let me just leave you with this thought. Many of you are fans of ReSharper the plugin for Visual Studio. You know, especially in the early days it did amazing stuff compared to what Visual Studio itself did. Visual Studio has adopted a lot of those features but still ReSharper is awesome. You maybe had the thought like Well, Visual Studio with ReSharper is awesome but what if the people that made ReSharper just made the whole thing they made the entire IDE and it came with ReSharper? Well that's basically PyCharm. Right, this is completely made by JetBrains it's the same people that make ReSharper. And it's just dedicated to working on Python code. And by the way JetBrains did eventually come out with their own IDE for C# and .NET as well it's called Rider. We're not really going to work with or talk about Rider. Just interesting bit of history there. But PyCharm is really a super great IDE for working with Python code as well as HTML, JavaScript database stuff, and so on. And that's what we're going to be using for this course.
|
|
|
transcript
|
0:42 |
Like I said before we're going to write a ton of code in this course. In fact, we have a whole bunch of applications that are C# applications, and the flow is going to be let's look at the C# version of this app and then go build it in Python. Now looks at this next C# app and then go build it in Python. So of course you're going to want to have the C# code to look at, and you're going to have the Python code that we create to explore and run and modify. So I want you to pause this video and go over to the URL at the bottom https://github.com/talkPython/Python-for-dotnet-developers-course and star and fork this repo so you can work with it and make it yours throughout this course.
|
|
|
transcript
|
1:40 |
Now, you're going to learn a bunch of cool little building blocks in Python throughout this course. How do I make a loop, how do I make a class how do I create a web app, how do I, you know render a template of eight dynamic HTML and so on, and so on. And these are super powerful to build up your toolbox but it's more fun to actually build a thing and I think you're going to learn a lot more. So, when you're taking this course I encourage you to do a couple of things. Make sure you've cloned the git repository, of course and then look through the C# version maybe even before we start that chapter. Play around with the code, it's usually one app except for in the first chapter, the language one where there's a bunch of super small little features we're exploring to explore the C# code maybe even before you start that chapter or right at the beginning as before we even dive into the first demo. We'll do that in the videos as well but I think it'll help you to get a little bit more accurate sense of what that C# code is about and then try to recreate it in Python. The goal of the course is to learn Python so don't start that first. Watch the chapter, and then once you're done with that chapter go and just create a new Python project take the C# code, and try to recreate it. Of course, if you get stuck, don't let that be a big deal. Just go back over to the real repository of the code you saw me write, and go oh yeah, that's how we do a for in loop, got it. And then go back and keep working, or whatever, okay? So I think if you want to get the most out of this course you should try to follow along, and try to build stuff and I think the way to do it here was to look at the C# code and try to build the equivalent in Python. That's what we do in the videos and I think it'll be a fun way to reinforce what we learned. We all love building things, right?
|
|
|
|
2:05:42 |
|
|
transcript
|
1:56 |
It's time to start to write some code and digging into the Python language. In this chapter, we're going to focus on comparing language features to language features. The Python language features to C# language features. And as you know in the C# side of things which is also true in Python knowing the language is not much. It's only the tip of the iceberg in terms of knowing how to use C# and Python is just like that. The language is great you do need to know it but there are so many libraries. There's the standard library which is like .NET's base class library. And then of course there's all the other libraries out there hundreds of thousands of them that we could use and that you need to know. This is just one part that we're starting to dig into here and we're going to focus on language features in this chapter. When you think of the Python language and the C# language depending on your background you may think that they're quite different, right? You might think well Python is kind of like this scripty language. It's a little bit like Bash, but a little bit more. And then C# is what you build real applications with with compilers, and runtimes, and all that. These two languages and ecosystems are way more similar than you think. Yes, Python has been used in a scripting context but it is used to build some of the most important applications out there and some really major ones. For example, maybe you've heard of YouTube or Instagram or things like this, right? It's used for really large and important projects. The language structure that you have in C# and Python is actually quite similar. Many of the things you care a lot about in C# and the language you'll find very comfortable and sometimes once you get used to it even better in Python. So we're going to talk about those now but I just wanted you to keep in mind even though they may look different when you first see these new language features or these language features in a new language they're actually quite similar to what you already know.
|
|
|
transcript
|
3:20 |
Before we get into the details let's just briefly look at the various language features of Python that we're going to cover, and how those map back to C#. We're going to start by talking about the language structure itself what holds the language together and defines its elements. And in C# we have things like curly braces, and semicolons. Python has neither of those. So, how do you define, like, an if statement or a function or a class, stuff like that? So this is what we're going to start focusing on. Then I want to cover loops. C# and Python have a lot of similarities but there's also a few unique and powerful features to loops in Python that we want to look at, because they're not obvious until you've had some time to work with the language and they're really powerful. Functions, functions are first class objects in Python similar to C#, but C#, all functions have to be contained within a class. Python, not so much, so they're a little more flexible in that regard. Generators, lazy functions, things that use the yield return keyword in C#, or maybe the LINQ extension methods like Where and Select and so on. You'll see that Python has something like this as well these great functions that are super easy to turn into iterators or generators so we're going to definitely talk about that. Ternary conditional expressions, delegates some of the terminology I'm using here is C# terminology but that's not what they're called in Python. But since you are C# developers I'm going to speak your language as much as possible when we get started here. How do we define a function that can be passed as an argument or accepted as an argument? Some of the best delegates are lambda expressions these short little functions that you can pass along without going to all the trouble to create separate functions. See, Python has great support for those as well. Closures, when a function captures data and holds onto it for the lifetime of that function which is pretty interesting. Type systems and runtime types think of Python as a dynamic language but actually all the runtime elements do have types and there's actually some static typing that we can use in the language. Error handling and exceptions, a lot of similarities here. Using blocks, the idea of for this little block of code, even within a function just a smaller block to find it using context where code is going to run and then outside of that something important's going to happen. A file's going to be closed, transaction will be rolled back something like that. We'll see how we work with these types of constructs IDisposable, and so on, in Python. Finally, the switch statement. Python itself doesn't have a switch statement but because it's a very flexible language there's some really cool things we can make, like almost like language switch statements. So, you'll see you can do some really interesting things there. Now if you look at this list, these are a lot of the things that you probably think, oh, these are really important to me in C# and every one of them has a great implementation in Python. See something missing there? What about classes? Do we have classes in here? No. Don't worry. Python, of course, has classes in object oriented programming, and all that kind of stuff. Because it is important, we're going to treat that as its own separate chapter. So we're going to over the idea of classes here but that's not because they don't exist that's because we're actually treating them with a little extra love and care later.
|
|
|
transcript
|
3:53 |
Well enough with that PowerPoint let's put that away and get our hands dirty and really start focusing on the code, and the editors and creating some little applications. Little in the beginning, slightly bigger at the end. Before we get into the Python code, we're actually going to talk about some C# code, because almost all the things, not everything, but most of what I'm going to show you in Python we start out by looking at it in C# and then creating it in Python. So for each thing that we do in the course you're going to have a nice analogy, here's what it was in C# here it is in Python, I can run and play with them both. If we're over in the GitHub repository notice there's a net, .NET but doesn't work super well in all the systems it would hide that directory for example. So just net is what I'm calling it right here and we have a Python section which is empty. I'm going to mostly stick to working on macOS not because Python doesn't work over on Windows but because it's a little bit easier for me and I'm going to give you a cleaner, better presentation of Python on macOS than I will on Windows just because that's where I work and all the hotkeys are broken for me on Windows. I worked on Windows for many, many years but recently the hotkeys there have been erased so, I'm going to just stay on macOS for the most part. We are going to do a little work with Windows 10 and APS.NET, at least in the beginning we're going to be here on my Mac. Now, doesn't mean we can't do .NET, but we don't have Visual Studio for Mac which is pretty cool they have this these days. We're going to work with the various programs. So this is the code that is already existing it's in the GitHub repository to start from and we're going to look at it. We're going to look at this chapter three language here. We don't have code for chapters 1 and 2 because those were just intro things but I decided to match it up with the videos. Over here we've got this shape of code so here's a simple, simple program that we're going to run and basically we've got a bunch of different things like here's for typing here's for turning our expressions and so on and they each have a run method which I'm calling from program. Yes, I could change the run configuration, the project about which one runs, but I find just always running this file and just un-commenting and commenting out different parts of a program is what we're going to do. So we're going to run this shape of code this should look familiar to you this should be very simple code. If you're a C# developer there's nothing fancy going on here. So we have a run function, it prints out on a single line and asks you a question at the end of that line what is your name? And then it just passes that off to some method, OK? So in this, the method here takes a string, a name and it checks if the name is, if you need to lower it trim it and all that, you know, ignoring whitespace and capitilization. If it's Michael it says Hello, old friend otherwise it says Nice to meet you and it's using this $ for string interpalation to print that out, instead of format, which is pretty cool says My name is C#! Let's run it. So here it asks what is your name? My name is Michael. Hello, old friend. We can run it again. My name is Bill. Nice to meet you, Bill, my name is C#!. Very exciting, not super surprising to you, right? So, this is standard C# code we have a name space, we have a class and then we have static or instance methods here's our static run, and then, obviously our other static method. Our if statements have parenthesis around them and there's curly braces creating them. Obviously for if statements and one liners that's not required, but in general it is and then all of our statements are terminated with semicolons, you should know this, right? But this is very different than Python. Now we have type names here, right there's a type definition about the argument as a string and it's return value is void, and so on.
|
|
|
transcript
|
3:01 |
All right, time for some Python. You've seen the C# code over here and we haven't looked at most of it but you can imagine the web part the website that we're going to build in Python the testing parts, the testing we're going to build. We're not starting from any code at all when it comes to Python. We're going to write every single bit of it during this course, which I think really helps you internalize it and see how it's put together in the whole flow. So what we're going to do is we're going to create a new project, we already started with our C# code with our solution and our projects and our project structure and all that over here so we're going to do that right now for Python. With Python, I could just create a file here and start working on a directory and then put a file in it potentially. There's not really a project structure I have to create. But I want to use something called PyCharm. PyCharm, which I already introduced earlier is a really excellent editor. If you don't want to use PyCharm then also VS Code with a Python plugin is super good similar setup here anyway. For Python, what we're going to do is you want to create something called a virtual environment. When you install Python, it gets installed into your system and it has some packages and libraries set up and some configuration. But if you want true isolation so this project has its own set of files and is completely isolated from all the other things that might have happened on your operating system what you do is you create this thing called a virtual environment. So we're going to create a virtual environment and then load this into PyCharm. So let's just jump into the terminal over here on it's a little extension I have called GoToShell and you see, there's nothing here yet. What we're going to do is we're going to create what's called this virtual environment and the way we're going to do that is we're going to type Python3 here. On Windows, you can, depending on how you install it you may or may not be able to type Python3 so just do Python but here I'm going to do Python3 -m to run a module. The module is called venv for virtual environment and the folder we're going to create is also venv. Now we have this folder here and this is basically a copy of Python and the entire Python run time. Sort of symlinks back, but basically it's a copy of Python think of it that way, at least conceptually. Now in order to use it, we have to activate it. So we can say source venv/bin/activate. And notice our prompt changes. On Windows, don't have this course source concept you say venv\scripts\activate.bat I don't know why those have to be different, but they are. Okay so now we have this as our active Python here. We can load up this project into PyCharm and when we install stuff like libraries we want to use think NuGet packages and other stuff like that what we're going to configure is this little local version this local version of Python, so whatever we do it's absolutely exactly as we want it and it's not affected by the other stuff. Not technically necessary but a very good practice so we're doing it right at the start of this project.
|
|
|
transcript
|
11:57 |
Our Python project is ready to create in PyCharm. We've created our virtual environment here and on macOS, you can load files and directories by just dragging and dropping them on here. On Windows, you would just say File, Open Directory but we get this little shortcut here. Now, we don't have any source files at all. You do want to check really quick in the terminal that your venv got activated. Turns out, in this case, annoyingly, it did not so we can go really quickly to the settings to the project, Project Interpreter and sometimes PyCharm detects it, sometimes it doesn't. I don't know why. You see it's detected it here and suggesting it but these are our projects we got in there or our libraries that just manage installs. This is kind of like NuGet for you all. Okay, so now, check one more time, notice this is here. We can ask which Python. On Windows, that's where Python, but it's the right one. So, what we can do is we can come over here and create a project just like we had in C#. We called it ch03_lang I'm going to make it lowercase. It's more of a convention in Python. There's more lowercasing of things so chapter, let's go with ch03_lang 'cause we're going to have more than 10. And in here, we can add a new Python file and let's call it program. So, let's remind ourselves it's been a whole couple minutes about what we're going to try to put here. This is what we want to simulate or to recreate, rather, in Python. We want to have a method that runs and is going to ask, what is your name? Get that, pass it to another method check that for lowercase and trim it and I see one of these two things based on the outcome there. Alright, so how do we do that over here? Well, it turns out to be pretty easy. We're going to come and we're going to define a function let's call it run at first. Let's call it main; that's a little more common in Python. Like so. Now, the way we define a function is we use the keyword def. Either it's a member function of a class or it's just a standalone function we define it with the keyword def. We do not specify a return value. More on that later. This one doesn't take any arguments and instead of having curly braces this is where it gets a little funky instead of having curly braces like this you can see PyCharm does not like the curly braces. It's like, no, no, no, something is really wrong here. We do use them but for other things in the language. It's as you expected, a colon. So, what we do is we'd write code and we define blocks. What would be the curly braces in C# in Python we'd say colon. Then what we do is a little bit funky the very first time you see it but it turns out to be really nice over time and actually, I love it a lot now these days is we indent four spaces. So, see when I hit Enter, PyCharm knows I indent four spaces and automatically did that for me like those are four spaces right there. Now, you might think, oh, my gosh spaces, not tabs, that's crazy. Well, it doesn't really matter so much because you'll see that editors make this more or less, transparent. If I hit Back, notice those four spaces got deleted. If I hit Tab, it goes forward four spaces like so. So, basically, and also, when I hit colon Enter it added those four spaces. All the editors, VS Code, PyCharm they know all about this structure and they're very good at helping you write it correctly or lint it back into the right shape if it's not there. So, what did we do? In C#, we said, next thing was get this what is your name bit here, we're going to ask that and then we want to get the name as a string. So, we're going to define a variable called name. We don't say string name, we just say name leveraging the dynamic types of Python and then we want to print on a message and get that value back from the user. That's super simple, we just say input and you put the string. That's it. So, we can go and run this now and just for starters, see what we're getting already. I encourage you to run, make little changes run, make little changes, and so on. So, what we can do, this is not really an important warning what we can do is we can just right-click over here and say run. It's not going to give you the outcome that you're hoping for but let's just run it. So, it ran it with Python from the virtual environment and you can see the argument way at the end is that file and nothing happened. That's weird. Well, it turns out that Python doesn't have this concept of a static main void that is the one and only static main void. You have to call the function at the very end of the file like it is at startup of the application. So, if we run that, does what is your name? Cool, I'll say Michael. It's cool with that, and we could print it out and see what we got there, but notice it did that little bit we were hoping for. However, because sometimes we want to run this only if we're targeting the application as the program but we might want to use this as a library and pull in other functions, there's this convention which is, albeit weird, but you get used to it is we put a little if down here and there's these implicit values that are defined for all the Python files, like __name__. We ask if that is __main__. Alright, so this is weird, but you get used to it and if that's the case, then we'd run main. And it's just not liking the spacing. Let's run it again. Operate the same. There we go. This is just the convention. This is the static main void of Python and because this is so common, I've created within PyCharm, a little thing called if main. If I hit Tab. Oh, I didn't create over here, let's go create together. It was in my other profile. Let's go over to Live Templates and let's just go to Python and let's add one. So, it's very common to have a main and we have this test down here. If... Alright, it says we also have to define a context. This is valid within Python. Alright, so now we can just say if main like this. So, we're going to use that throughout the rest of class which is why I took the time to show you that because we're going to write 20 or so programs I don't want to type that in, I just want to say we're just going to do this main trick. So, remember, what we had was name equals input what is your name? Like that. Okay, so that was step one. Now we want to define a second function up here and it was called some_method, so we say def some_method. In C#, we have camel case, like so, it would be like this. In Python, we have, well, snake case, which looks like this. Okay. This is the convention in the language so that's how we're going to do it. And then it takes an argument name but we don't say string name, just like we don't up here. We just say it takes a name. Excellent. Now, what do we have to do after this? We had an if statement, so we're seeing a little bit about if. We'll come here and say if, and then a boolean condition and we don't have the parentheses, we omit them. I'll say some more about that in a second but let's do this test here. We have name dot. Now, it doesn't give us a lot of help here. We can trick it, and I'll show you how to do this more in a second, but if we go down here and type this, notice we actually get autocomplete for all the string information. We can actually specify some type information here and PyCharm would totally pick it up. For some reason, it's not. Oh, hold on, I think if we were to call this it might actually automatically do it. Will it? There you go. So, you can see, PyCharm's actually understanding the types the real runtime types, that are being passed around as we're using them here. So, now, it's like, oh, you're calling this function with a string, that must have string operations on it. But there's a way to actually specify the types if you want as we'll get to. So, what have we did? We did a trim, which, in Python, is a strip and we did a ToLower, which, in Python, is just a lower. We said if that's equal to Michael, like that define a code block here, like so. I'm going to say print, that's like Console.WriteLine hello, old friend. We're going to do it just the same. Colon and print. Nice to meet you, and we had the name here like this, right? Well, it turns out, the string formatting in Python and C# is almost identical. We could do a dot format and pass a name value over just like you can in C#, but we can also remember, in C# we had a dollar, in Python we have an f for formatted strings, and now notice name is lit up like a variable. And I'll also have the other one print my name is C#. Exclamation, you're not Python. Here we go. Alright, well, there's a little warning that we need two lines by convention between those so we can tell it to autoformat. See down here, you can see the code the key that I'm running, the hot key there. Okay, I think we're ready to run it. Have we created our C# equivalent in Python? I think we have, what is your name? Michael. Hello, old friend. Let's try again. Sarah. Nice to meet you Sarah, my name is Python. Super cool. This probably looks a little bit weird to you if you've never seen Python and you're like what is this space stuff? This space is crazy. But like I said, it actually, you don't really deal with spaces even though they're technically present in the language. These colon blocks are interesting. The if statements here, notice, I could actually do this if I was missing my parentheses I could put them in there and it would still run still runs okay, but the warning is these parentheses are not needed. You can get rid of them. Actually, a lot of things like that are optional or just missing in Python, and it's really, really nice that you don't have to put them. First it feels weird, later it's weird to require them because if they are not really required why do I have to type them all the time? Okay, so this is that program. Let's go and look at it again in C#. I'm going to try to put these things side by side for you. So, let's see if I can side-by-side this here side-by-side that. Alright. Well, you got to forget this part for a second 'cause there's a separate file in the C# version that represents that. This is the program.cs that has a static void main. Look at this. The Python one probably felts a little weird to you if you haven't seen it before and if you have, maybe it's fine, maybe it's no big deal but if you haven't and you're like wait a minute, there's no parentheses here and this colon thing is kind of funky and so on but there is something nice and beautiful about that code on the left compared to how many symbols there are on the right. There's so much syntactical stuff in C# and whatnot that I feel like it almost makes it hard to read because it's just covered in a lot of curly braces and brackets and static void this, static void that and so on. But let's just look at them side by side. There's a lot more stuff on the right-hand side that just doesn't need to be there. These are the ways that we define code structure in C# curly braces and semicolons and in Python, colon and whitespace. If I come over here and I unindent, print other this is not in the main method. This is a separate line of code that is kind of after main is defined but then just executed when you import the file. If I run this, you'll see, it first prints out other. Oh, I took away that thing at the bottom, didn't I? Because I wanted to compare them. But now if I run it, you'll see other and then what is your name, right? These are not in each other. It's the indentation that defines the structure. It takes some getting used to, trust me but once you get used to it, it's actually delightful.
|
|
|
transcript
|
2:34 |
Now lets quickly review the shape of a Python program. Or the shape of code structure within the Python language. I want to make a quick comment though about these little review segments these metacomment if you will. Some folks have said, hey we've just talked about this why are you showing me the same thing? I'm going to show you the structure and so on and highlight a few important things. One, well, I think review is important and we talked about it for twelve minutes let's summarize it in thirty seconds. I think that's helpful for remembering. The other thing, though, this is meant to be reference material for you. These little tiny things are super easy they're going to be separate videos you can just go back and jump into and look at. Oh, how do I do iteration with something like IEnumerable collection? I'm going to jump into that concept review really quick and just catch that in two minutes, right. When you're coming back a couple months later most video courses have a really bad or they're just absent of any reference material so these are your little reference points you can come back really quick. Stepping out of that metacomment there let's talk about the shape of a Python program. Python defines code blocks, technically called code suites but I like to call them code blocks so I'm just going to keep doing that and it uses colons to initiate them and then white space to define what is in it. So, here's a single source file that I've put a bunch of colored boxes around to highlight each code block that is happening, code suite if you will. So, everything here, these are all code suites. The blue boxes, they're defined by the def some_method and then a colon or def main colon and then anything indented in four spaces or more is defined to be within that code block. And then, we have an if statement in there and a colon, and we indented four more. That's a print hello old friend. Then else, that's a not indented, different code block colon, indent, that's a bunch more. We have two print statements in there, and so on. So, this is Python's alternative view of the world on structuring code. Instead of using curly braces and semi-colons use colons and white space. A couple things to note: Obviously no semi-colons, code blocks start with a colon but white space really, really matters. There are no braces, there's no parentheses tab as an item inside the file is not your friend. These have to be spaces, but all the important editors know that, and when you press tab, it puts four spaces when you hit delete, it removes four spaces things like that. There's actually an exception like, hey I found a tab in your code exception type in Python. Alright, so this is how Python defines the structure of code. It might seem unusual at first but trust me, you'll get used to it and it actually works out really nicely.
|
|
|
transcript
|
2:04 |
Next thing in C# I want to look at and then create in Python is loops, different kinds of loops and iterations and things like that. So here we have a simple C# program and it's going to start having a loop here. It's going to come through and say while true, it's going to ask the user, what is your name and it's going to greet them as long as they enter a name. If they don't, it's going to break out. I guess we could really shorten this if we wanted as Visual Studio was suggesting, there we go. I just want to read it in, check it, and break out. We're also then going to take an integer array here. We have a pre-defined nums, it contains a bunch of integers. 1, 5, 8, 10 and so on. And we're going to use one of the nicest features of C# in terms of iteration stuff, I believe is the foreach loop, right? So much better than the for loop, which is down here. So in the foreach loop, we're just going to round. The next number is this. But it has some shortcomings like maybe I want to say the first number is this the second number is that, the third number is that. We're going to fall back to our for loop and get that number, but also have the index say the first, second, and so on. Let's just run this program real quick. I changed program over here CS in this project to run that one. We run it. It says, what is your name? Remember, it's going to ask me my name and keep greeting me as long as I say a name so I'll say my name is Michael. My name is Zoe. And if I'm done, I hit Enter. It's going to go to the next section and just work with the foreach loops. So here it loops through those numbers. The next number is 1, 5, 8, 10, 7, 2, great. The next, next, next, how great is that? We said no, no, no. We're going to use a for loop and we're going to have the first number as 1 the second number is 5 now obviously it should be first, not firth or however you pronounce that right there. But we're not going to sweat the details. We could obviously add that adjustment for the suffix of these letters but first is 1, second is 5, third, 8, and so on. This project in C# works with most of the structures of looping that we have in the language.
|
|
|
transcript
|
7:30 |
It's time to write the Python loop code and explore the different types of loops and ways we can work with iterable objects in Python. Now, quick note, I renamed this from program to L01 For Language Part 1 Structure I'm going to create and partition this a little bit. So, I'm going to have L02_iteration that's going to be the way we want it to run. Remember we always start by having the main method and then that if thing that I created with if __main__, we going to write it like that really quickly. And in our main method, we're going to do some exploration. You could actually just put the code right here you don't need a method but I don't know, that's just seems wrong to me so I'm not going to do it. So, let's do what we had before, we had a while loop and in Python, we have while loop as well. But we have a for true written like that we don't have that in Python. We have a capital T, True. So True and False, the Booleans are capitalized. So, that's fine. We wanted to find the block of code here and what we did is we had name variable and we ask the question What is your name? So, What is your name? So, we also at the very beginning, we had a Python iteration demo. Something like that, right? Then down here, we had an if statement, we said if we had string.IsNullOrWhiteSpace We can do something like that, we can just say if not name like this, you'd have more sort of truthiness in objects in Python than you do in C#, everything has to been exactly a Boolean. We can just say, is this string False, right is it empty or something like that? We can break after there. Otherwise, we going to do print with a formatted string Nice to meet you + name something like that. All right well, that's pretty straight forward isn't it? Lets run it. That looks really similar, exchanging the code structure a bit as we had before. So, down here we can say What is your name My name is Michael, Nice to meet you What is your name, My name is Zoe. If I enter, it breaks out, is done. So, that's this part right here. I'm going to comment that out for a second so we just focus on the next bit. We had some numbers over at the C# version and I'm just going to grab amount, so we have the same thing, so just going to copy those over. Now, we are going to define some numbers in Python an integer array so we had nums, we don't say the type, it's dynamic at least for now unless you want to add the types, like I said we'll talk about that later. And we put brackets, paste. So, this is not actually an array, in C# we had a static array, here we have a list. So, this is like list of int or more like list of object equivalent. In the C# equivalent would be the list of object here, all right, pre-allocated. Now, what we want to do is we going to go and have a foreach loop type of thing, and I told you, it was one of my favorite thing about the C# language coming to it from C++ is like Whoa! This is so much nicer. Turns out Python has exactly the same construct, the rules about what go into the loop are the same and has to be iterable kind of like it has to be IEnumerable in .NET But it's not called foreach, it's called for. So, the way it works is that you say for like this. So, this is like foreach in C#. And then, what do we have, we just print it out the next number is n. Well, that's pretty straight forward right? Really nice that there is something like if foreach loop, words are not exactly the same but what's really interesting is that there is no for that does not exist. There is none of this. Alright, so I'll put this down here. It turns out that we can simulate this kind of loop in Python but there's not an actual integer for loop. This is the only kind of for loop in Python as is for. Alright, well, let's just run it and see if it works. Boom! The next number is 5, 8, 10 just like we had in C#. What we did though in C# is that... Well, we wanted to say the first number is this the second number is that and so on. So, we said alright, fine. We'll break down using the for loop. We're going to do something even better in Python. Check this out! So, Python has this concept of tuples this group, two or more things that is kind of like a list, you can iterate it and stuff but what's really interesting about it is I can have like two variables to find like this. Let's say x, y = 1, 2. This would create a tuple and assign 1 to x and y would get 2. We can use that in this little loop here I could say I want index and the number and I can not iterate over the collection but I can iterate over the enumeration of the collection. Enumerate nums and I can even say start = 1 and then we can come to here the idx how we had it, numbers this. We don't even have to plus one because it automatically goes 1, 2, 3 not zero 1, 2. Alright, let's run this. Let's put it also some space between them. How cool is that! That is a super slick way to loop over those and it's much better than what you have to do if you resort to this. So, you can see this for in loops are really really flexible in Python. Final thing is sometimes you want to just do a thing 10 times right? And this for actually it's really useful for I want to do limit times. We also have that in Python and it leverages this idea and natural support for ranges. So, I could just say for n in range of one to 11, it's a... So we go one up to 10 inclusive, not the last one and I can say print again or this time or I don't know, something like that. Let's put a little separator here and let's actually make that just run five times. So we run this again. Then, 1, 2, 3, 4, 5 times we said this time. All right, so that's really cool. This is like your for right? But we're not using this n here, there's a convention in Python to say there has to be a variable define here, you can't just put nothing here, that's going to be an error. There's a variable that has to go here but I specifically am stating I don't want to use it, I don't care what it is and that's underscore. So, all the Linters and code-checkers and stuff when they see that underscore, they will not warn you that underscore is not use but they would warn you that n wasn't use in that case, potentially if it weren't use up here, right? So, let's run it one more time. Same thing. Alright, so this is loops in Python and super good news, your for-each loop, you still got it and it's actually I think a little bit better than .NET.
|
|
|
transcript
|
1:31 |
C# has the foreach loop. Python has the for in loop. So here's a list of numbers that we were working with we want to just loop through them or any collection, anything that is iterable in Python's terms. We just say for n in nums: and then we work with n. We just loop over a collection like objects. These can be lists or arrays. These can be strings these can actually be classes that just implement the right interfaces and we can treat them like this. If you want the idx that goes along with an item in your for in loop we just use enumerate. So, enumerate(nums, start=1) instead of just for n in nums. Then we have this tuple projection we get a tuple back when we assign it to two variables its elements at two variables the idx and the n and here, we can say, we can work with the idx n in each time through the loop. We also saw that Python does not have a numerical for loop but we can get back to something really, really close to that, super easy. We can just say for i in range and we give it a range, zero to 100. And that'll go from 0 to 99 stepping by one, right? And then, we just work with i and change things like the step and so on so there's a lot of flexibility there. But there's no traditional for i = value i < such and such that you get from C#, C++, Java and so on. Alright, that's it. Looping in Python is a joy.
|
|
|
transcript
|
2:22 |
The next area that I want to focus on for you is functions. So, we've already really sort of been using functions in Python. You saw we've had our main method and our some_method and took an argument, but I want to focus specifically on what are the parameters, what can we do in terms of flexibility, return values and all sorts of stuff like that. Method overloading, and so on. So we're going to write, at the first start exploring this we're going to write a little game, it'll be a lot of fun. And then we're going to come back and focus on specifically on, method overloading type of operations. So here we have a program in C#. And let's just run it, I think you'll enjoy. It's a high low game, so it says I'm thinking of a number between one and 100, how many steps can you guess it in, what number am I thinking of? This is where you apply your binary search algorithm 50 too low, 75 too low 90 too high, 85 too high 80, 76, 77, 78, 79 it must be. There it is, of course, I was thinking of 79. Well, my little binary search didn't work that well and I kind of broke down there when I got to the 70s but nonetheless, we're going to write this program in Python it does things like go and get the guess from the person and so on. So, it should be a lot of fun let's just really quickly look at the code here before we go talk about it in Python. So here's our main method. We've run it and it says ShowHeader that's the big little printed bit at the top there that says, Welcome to the High Low Game. We create a random number generator and we get a random integer between one and a hundred. And then we also keep track of how many times this happened. So when I go through, want to get a guess if they don't give us a guess it's a nullable integer, if they don't give us a guess then we could just tell them, hey, no, you've got to give us a number, ask 'em again, something like that. Count how many times they give us real guesses and evaluate the guess, right here we're passing the value of that nullable type in the number and then if they get it right they break and we say, good job, you did this many times, all right. So pretty standard C# down here, easy six lines for what it's worth. We'll want to come back and look at this in Python as well. All right, so this is the game that we're going to recreate over in Python to explore working with the functions.
|
|
|
transcript
|
10:09 |
Here we are on the Python side over in PyCharm. And we're going to create that high-low game again. We're going to start by defining our main method and the __main__ convention. So that's my little live template we created. And the first thing that we did over there is we said I'm going to show the header. That's the big welcome to the game. So we'll say show_header, like that. And this one calling a function that has no parameters and we don't really care about the return value. And PyCharm you see will actually create this for us. I really want to do it just once but I don't really like how it does this. So notice it went and created the function just fine. If you want it to be empty, you can use this word pass and that's also fine. But what I don't like is that it put it above main. It put it above main because that's the safest option. And it's not convinced that we're doing this in the right time and place. But I like the main to be the top and then all the stuff after it so I can see the overall view of what's happening in this program and then the details. No, I'm going to put this down here. Alright, that's why I don't use that little auto-generate bit thing so much. And here we just have a little print statement. I'm just going to paste it 'cause there's no real value to watching me type this. So it just changed the word C# to Python here. And that's what we got. So we'd run this one. Notice it's got a little header and that's it so far. Okay, so what's next? We can put that away. The next thing we did is we actually generated the guess, the random number. Okay, so what we did in .NET is we said Random rand = new Random() like this. Alright, that's what we had. And we had to have at the top using System for that to work, right? Python has something very similar. If we want to use the random library from the standard library that comes with Python, we have to add an equivalent statement like this to say we'd like to reference or refer to this part of the system. So the way we do that in Python is we say import. And there's all sorts of stuff we can put up here. One of them is the random library. So we say import random. And down here we would say the guess. Alright, this is sort of two steps here. We also had the guess is rand.Next or something like this. I forgot the function. Alright, so we had that. So then here we're going to say random.randint. Now, this takes two values. It's not super-helpful about what it is. But it's two numbers, I believe inclusive. We can always say view quick documentation. Yeah, so inclusive A to B. So we want to go one to 100, like this. So that's the guess. And just for a moment, let me just print the guess. Now, obviously you don't show it or it's a pretty boring game. But just so you can see that we're making progress here. Alright, so we guessed 83. Good, we're on a good path. I'm not going to do that again. Then what we did is we went around and around asking What do you want to do? So we had a while loop and we said while true. We're going to say the guess is equal to 1 and get the guess from the user. Alright, so we have a function that's going to return a value back here. We also had the count. That equals 0. And each time through, we would increment this counter, right? So we'll say, we wanted to say if they didn't give us a guess, just ask them for a guess again. So if not guess. Before we checked whether it was null and things like that. We can just say use the truthiness of this here. It'll return none or an integer. And we'll say continue. Exactly like C#. Now, we want to make sure, okay, we're recording this check here so we're going to say count. In C#, we had this. Python, for some reason, doesn't have a ++. I really kind of wish it did. So we do +=1. Basically the same thing but, you know, ++. I'm kind of a fan. And then we need to evaluate this guess. So we'll say if evaluate_guess. So when I give the guess that the person gave and we'll also have the, call it the guess. Let's rename this. Use a little refactor rename. Say we're to current rename all the, I'll put this to the number. There we go. That's better, right? We're going to evaluate this with a function that doesn't exist yet. And if it's true then we're going to break out. At the very end, we're going to do a print statement that says something like this. You got the number in some number of attempts. Thanks for playing. Alright, so the last thing to do is write our get the guess function here. So let's go and say def get_guess. And remember what we do in get_guess. Well, a couple of things here. Sure, it's easy to just ask for the number from the user and then just convert it to an integer. But we want to do some validation here, right? So we'll text. We'll put text as input. What number am I thinking of? And then we'll put, let's put the value is going to be convert this to an integer from text, right? This is like int.TryParse. First thing we want to do is make sure they're guessing between one and 100 so we'll say if val is less than one or in C# and a lot of the C languages you say || for or, right? In Python you just say or and and, right? And would be the other one there. And it would say that or 100 is less than val. Alright, say nope, this number's not in the right place. It won't return Python's equivalent of null. We don't have null here. We have none but the meaning is the same thing. And if that works, we were able to parse it into an integer and it was like this so we could return the vowel. But just like .NETs and .Parse, this throws an exception if you put in something like that, right? That's going to be exception. So we got to do one more layer here. We're going to talk more about error handling in detail in a minute. But let's just deal with this like so. So if you try to do this and it fails instead of catch you have except I'm going to return None as well. So those are the two cases. Maybe we'll put a little note in here as well like print. Whatever that was, it's not an integer, okay? And just so it doesn't freak out, right. It's always defined somehow. Okay, so this should get our guess for us here. And the last thing to do is just to evaluate it. Let's copy this over so I can not have to type too much. And I'll just put it right here. Again we say def. Now we take the two parameters, input here. And just for the sake of time, let me just drop in some code real quick here. And I'll just make that a number. So we say if the guess is equal to the number, that's it. I was thinking of the number. If it's too low, too low, too high, and so on. And then we're going to return True or False. Is this equal to the number? And by the way I have this type of font installed on my system that will convert things like double equals to have, basically look like one long equals. And if you say not, like if I say not equals and I put that together, it slashes through it or less than, oops, take that away, less than or equal to and so on. So you might see some funky characters. Anyway, it's just that font there. So it just means two equals, right? Nothing funny about that. Okay, so this is our evaluate guess. I think our program should run. We've imported our random library. We've called a function on it, got the number doing our guesses. Yeah, let's try it. What number am I thinking of? I'm thinking of 50. That's too high. Oh, 25, 15. Jeez it's low. 10, 5, yes. It was 5. You got 5 in 5 attempts. Thanks for playing, bye. That's a pretty good little program, huh? Not too bad. And let me take, let's just account for the fact there are two comment lines there and I think that that's it. Right, so what do we have in C# for this? We had 86 lines. Kind of the empty line. In Python, 63. That's 23 fewer lines. Format this? No, everything's formatted correctly with the right spacing line separation, all that. Alright, so here is that game. Actually, remember, take this two out as well. Super, super-simple, really nice. The way we do arguments is we just pass them in like it's almost exactly like C#. Same here, you just don't define the types. There's actually a lot of flexibility when we get to that in the next section the very next section. But if you don't care about specifying the types or default values or stuff like that, you just say the parameters here. The other thing is you never specify the return type, right? In C# you always have like string or void or list of task of I don't know, int, right? Something like that. We don't put any of that. And the reason is one, we don't say the typing necessarily. It's sort of optional these days in Python. But the other is every function has a return type. What does this return? Well, this returns a boolean because that's what we're returning. But what's less obvious, this one also returns something. This is, there's an implicit return None. If you don't specify a return type for a function its return type or the, actually the return value, is None. Every function has a return type. There is no concept of a void function. It just happens to be they return None or null when they don't specify anything. All right, so these are the basics of passing arguments into, calling, and getting the return values of functions. It's actually super, super-similar to C# with the exception of this implicit return type.
|
|
|
transcript
|
0:56 |
Creating Python functions always start with the key word def. We're defining a function. We give it a name. This one we're calling evaluate_guess following the Python naming conventions of snake case not camel case. Then we can optionally in this case, we want to take some arguments here So we're defining some parameters, guess and number. They're positional, but you can also use them keyword style. And then these functions have the implementation and they always have a return value. So here we're explicitly returning the single value that we can, which is True or False. Is the guess equal to the number or is it not? But if we don't specify a return value the value will be None. So if you think of functions as always like returning nullable of something something to that effect even the ones that you would conceptualize as void functions, those return None so every function always returns something just sometimes None.
|
|
|
transcript
|
2:46 |
In this next section, let's look at functions and how we can have them behave differently depending on the arguments we pass in. So for example, here's one called SayHello and we can just call this with no arguments here's one where we can call SayHello("Zoe"). I'm going to say SayHello("Zoe", 5), and then "Zoe", 5 and then some arbitrary number of things, doesn't matter how many there are. I guess I'll put four there. How do we do that? And here we can also have it behave differently on the type of argument we're passing in integer versus a double. So this is part of C#'s static typing it's pretty easy for us to do this and it's flexibility in defining functions. So let's look at it first in C# and then we'll go recreate this as much as we can in Python. So let's just run it real quick and we can see what the output is. So when we call it void, it just says hello there friends, and it had some default values and it has extra values it could pass over. These are the params, arguments that we'll see. If we call it with name, the name's value is Zoe so instead of saying friend, it says Zoe and then we called it with names and 5 times so it says hello there Zoe, and this value is 5 and so on. And then we had, I didn't update this 1, 2, 3, 4, so the extra values that got passed here were 1, 2, 3, and 4. Then when we call it integer, we SayHello(5) it actually does that five times. And if we call it with a double it repeats the number of times but it says hello there double times. This is a totally different function if we pass a double than an integer which is also different than any of these. But these actually turn out to be the same one with default values and params. Alright, so let's look really quickly at that. So down here for the one that gets used most of the time, we have the name which is required, and we have a times which has a default value of 1 so it's optional, and then anything else that gets passed gets captured in this param object array called extras. It'd be nice to just print out what that is but it just says it's a list or an array of objects it doesn't tell you what the values are so I had to write this little function in C# to print that out. We want to call it void, here's the void overload that just says hello friend. And you see it delegates back to this one by passing friend. This one, if you pass in times, it says hello there some number of times, and if you pass in a double same basic thing, but it says hello there double time. So we're able to select between this function this function, this, and this, based on the arguments that we give it. And we got those different behaviors that you just saw there. Like that. That works pretty well, and it's pretty common in C#. You want to see how to do it in Python? That's next.
|
|
|
transcript
|
6:08 |
Let's see function overloading in Python. Want to start without with our standard structure here like this. And in here, remember, what we had in C# was calling it with different parameters. I'm just going to paste a bunch of coding here so we have something really, really similar, okay? So we're going to call it, say_hello, say_hello("Zoe") say_hello("Zoe", 5), I think I updated this to have four, so let's do that, and so on. Now, we're going to comment that one out for a sec let's define this function that we're working with here. def say_hello. And then what do we want to do? Well, let's put a little print statement here that just prints out the values. First it'll say, Hello there. So turns out that's going to work great for this one but PyCharm is kind of warning us maybe something's not super about this. Right, unexpected argument, unexpected argument, and so on. Let's run it, we'll get through a little bit. That said, say 'Hello, hi there, hello name' and then it crashes because we got to the Hello name in that one, right there, that's not working. So how do we add this? In C#, what we do is we had an empty one, like this and we said, want to call all the say hello one with friend and we had a name over here, Hello, name, like that. It turns out Python does not have this concept of two functions with the same name but different parameters and see here, there's this problem and it ends up it's going to say basically only one of these is going to survive. And what actually happens is there's not even an error this is really super frustrating about Python this definition of that say hello simply replaces that one because it's later in the file. Think this is a shortcoming in the language but anyway, what you're going to find out is it's as if the code was only that. Well then obviously this line doesn't make any sense. So this process of how we did it in C# doesn't even make any sense, it's going to go the wrong way. So what we can do here instead is we can say This is friend. Okay? So we'll have our default value but when it's like that, it'll be friend and this one hello, so that's kind of what we did in C# but we did two functions, now we're just doing one with a default argument. Could've done it that way in C# but I wanted to show you more of what's going on. say_hello, it says Hello, friend say_hello("Zoe"), it says Hi, Zoey the next one crashes right there. So this next one is, this is how many times we want it to say hello or something like that so let's... in here we have another parameter and we have times=1 and that solves that problem. That's pretty cool. So with times equals times... And that'll get us farther, as we'll see. So it gets us to this, but again when we call up this one, it died. And we just click here to go right to that line. How do we deal with this variable number of arguments? Well, in Python, we-- C#, let's step back we had params, object array, args. Python has the exact same concept but they don't like all those words so they just put *. And we'll say args equals args, like this. Python just prints arrays I don't have to write print array here, that's pretty sweet so if I run this again, I can see the args are like this. Let's do one more thing here let's suppose in this one we wanted actually do one more line, like this. Let's suppose we wanted to say val=7 mode=prod, something like that. If we want to write code like that, here yeah, I think I'll be able to make it work. Line that order, come down here like this. We have to come in and say this takes also arbitrary keyword argument so here's our arbitrary positional arguments. So the way you say that in Python is you say, **kwargs, like this. Now that's happy up there and we can print kwargs={kwargs}. This becomes a dictionary where the keys val, value 7, keys mode, value prod. Run it one more time. Beautiful, look at that, it's working like a champ. So here's that additional bit. So this is an additional level of flexibility of passing arbitrary arguments I don't think C# has I don't remember it having, maybe it does but they definitely have this, but this is also super nice to be able to take additional keyword arguments on top of just the positional ones. So we could actually pretty much implement this one as well and it's, I'm not going to it says basically the same thing, so we're going to drop it. Here we go, this lets us have arbitrary positional arguments arbitrary keyboard arguments default values for these, and these are positional ones. That looks pretty good to me. You may remember, there were two other ones in C# that was like this, where you said say 'hello integer' and it did something different and it said say 'hello decimal' and it did something different. Technically speaking, we could do something stupid like this we could say, if isinstance, name, and what've we got here an int, print, all right, could do print int version da da da da da, else. Technically possible, I think it's a bad idea. I would not, in fact I'm going to delete this. Just not a good idea, I wouldn't do it. Basically this type of overloading by type under the one argument, and it's the type that determines which function gets called it's not something that works in Python. But all the other types, the default values the void ones, the additional parameters the named ones, all that kind of stuff works really similarly to the way you'd expect it does in C#, but this type, this last two here this type of overloading just doesn't exist 'cause you don't base which function you call on types right, it's just not how it works.
|
|
|
transcript
|
3:20 |
Let's quickly review functions in Python. Here, we have a function called named arguments and it has one required positional parameter called name, ironically. And then, it takes arbitrary positional arguments *args, remember that's like params, object array but we just say *. And then, we can pass arbitrary keyword arguments to it and that appears in the dictionary, kwargs. I don't really love that style because it doesn't tell me what arbitrary keywords I could pass. A way to accomplish almost exactly the same thing like 90% of the time, if you just have default values like this times here. If you could've said times=1 but you don't have to, well, you could also just say times=1 as a default argument and it turns out the editors give you way more help because if ask what is the signature of named args in the top one, it tells me I can pass anything. I don't know what type those are. I don't know the values of them, the names of the parameters are, the list of options, nothing. And this is prevalent in Python and I kind of hate it because usually what you can do is just name out the optional named arguments as default values and folks can decide to pass them by name or not, right? So really, really nice to do this second one. I feel it's better than the top one. There's a few use cases where you really don't know what could go in there 'cause your passing it along but most of the time, you actually know. It's just you don't want to say. So anyway, I kind of like the bottom say hello version over the named args. One thing you do want to be careful about though with these default values here, these can be dangerous. So see this say no, as in no, no, no, don't do this? This one actually is a bit of an anti-pattern and let me tell you why. If you pass a mutable type or if you set a mutable type for the default value, this could go really, really wrong and let me tell you how. You might think when you call this function the default value is created and set each time the function is called but that's not actually where the default value is set. The default value is set when that module, that file is loaded, once, ever, so there is a singleton list that is the default value for names. That singleton is, well, it's a singleton and that means it's shared by everyone who calls that function every time. So imagine something happens inside that function where names is altered, right? An item is added or removed to names if it's empty. Well, guess what. Now the default value has that change reflected in it or worse, if this function returns names makes some changes, adds more names and returns that list, then it's open to the rest of the program to possibly add or remove items from that default value so never, never put a mutable value here. The way you would accomplish this is you would say names=None and then, in that function you say if names is None, names=[], like this. And that way, you get a new copy every time you call it not the one that got set when you imported the module. That's super not obvious, so I wanted to call it out and make it really clear. This seems okay but it turns out to actually be an anti-pattern.
|
|
|
transcript
|
3:46 |
This next section, I want to cover something that I think is probably underused in C# and in Python and it's such a cool idea, generators. This is the yield return keyword and things like that in C#. So let's look at a real simple example here Fibonacci numbers. So we have two versions. We have the naive version of the Fibonacci sequence that you might write and if you don't remember it's 1 and 1 and then you add the two numbers together and you get 2 and you add those two to get 2 and 5 and then 8 and then 13 and then 21 and so on. Right, so that's the sequence that we're working with here. Here's a simple standard function. Return something IEnumerable of integers and you say I would like, I don't know five Fibonacci numbers or six or 1000 or 100,000 and what it does is it creates a list it does the algorithm, puts the items in the list as it computes them and when it's done it returns them, great right? This is a standard function it returns a basically a list that we can iterate. However, this is an approximation of the Fibonacci numbers in fact, right? The Fibonacci sequence is infinite. How do you know how many to ask for? Things like that, it can be tricky. So here's a better one that has no limit. See while true and it returns IEnumerable<int> and at each step it uses the yield return keyword to return a single integer. So this is how yield return works in C#. We yield return an item of a collection. We say we have a collection of integers and here is one and here is one and here's one and it will just keep generating these until we stop asking for them. The trick to make this work is we're going to to through them in this foreach loop and get an item out and then if the item is big enough then we're going to stop asking. So let's go and run this. Look at it go, runs and runs and runs hits an item, hits an item. If we put a breakpoint here this is when it gets pretty interesting. So here we are in our foreach statement and if we step in it's going to do what you expect. It goes into the function and great so we're stepping along here. I'll go into while true loop it's kind of crazy that that returns out of there but okay that's how these work. So it's going to generate the first item which is 1 and it's going to return it and go back to the loop, okay? There's one and is equal to 1. We're writing it out and if we keep stepping we step back into our Fibonacci sequence but we jump to this line after yield return. Notice even though current started out at 0 it is now 1. And this is not because I ran to this place in the function, no. It actually resumes. These are like restartable functions, these generators. If we step through here, we're going to do again. Get this, now we're back here and now n is probably 1 again. It's going to go 1, 1 and then 2 and so on. So it just keeps pulling them one at a time as we iterate over them. And the result that we get is it generates all those until we stop asking for it where we said if it's over a 1000 stop. All right, so this is generators and the yield return keyword in C#. Super powerful, it's the foundation of things like the lazy evaluation of things like LINQ for objects and so on. I don't think that many people use it but it's really powerful when you want to start work with a collection or generate a collection or something like but you're not sure how much you want to take. You want to just pull them one at a time. Really, really nice. Yield return keyword, C#, love it.
|
|
|
transcript
|
4:09 |
You saw generators and the yield return keyword in C#, was super cool. Let's see what Python has to offer. We're going to see, actually, some of the implementation here might be even better than C#. So, just to jump-start things a little bit I've added the standard counting finite version. Let's print out 10 of these Fibonacci numbers here. We can do a cool trick, here we say the end is actually the inline, instead of backslash N backslash maybe backslash R backslash N, or just back backslash N is actually comma space. So we'd run this, and you run the correct one what do you get? Get a cool thing like that. Okay that's neat and those look like the Fibonacci numbers to me. And of course there's the implementation. But this is the kind where you ask for a certain amount and we saw that we can use generators in C# to make a really cool version of this right so let's see what we could do there. Go like that, and we had while true and there was some stuff in here we had this but we didn't have the list we just used this yield return keyword to say here's an item. Maybe we could shorten this, to like this if you wanted. A little more condensed say here's our starting state 0 and 1. I didn't use the word next, because next is a function that's built into Python and it would conflict with it so just this of course that's capital. So check this out, here's the implementation in Python you can see it below as well. So you say, use your tuple, packing and unpacking so current and nxt is equal to nxt that's the value of current. And then nxt = nxt + current. Super cool. Now how do we return this and generate this iterator type of thing, that we saw in C#? In C# we said yield return item, here we just say yield item, that's it. That is the whole implementation of the infinite Fibonacci sequence. And by the way, integers in Python are effectively big ints they can be billions or huge, huge, huge numbers that don't even have names without overflowing unlike say 64-bit integers or longs in C#. Now this, is obviously not going to work we passed the value here so we need to do something like this, if in is greater than 1,000 break. I think to be exactly precise, we had that before. There we go, let's run it again. Oh, just like that, it's exactly the same, except for let's do a little side-by-side here. See if we can fit it on the screen. Not really but we can at least get the for loop on there. Get it up so we got the for loop. Check this out folks. So here's the C# version, we're doing all of this and then here's the generator and the implementation in the Fibonacci, look over here, here's the top function going through them, if it's the same break out. Do the print with a comma on the end. Here's Fibonacci, there's the Fibonacci implementation versus this in C#. I mean it's glorious you guys. It definitely is a little bit different structure and it takes a little bit of getting used to but there's a lot of examples like this where you're like actually that is really simple and clear and this is kind of symbol soup, there's symbols everywhere. There's like this generic type up here, there's the static and the public, and the curly braces, and the semicolons and the integers and whoo yes they have purpose in there they're not lacking value but they definitely sometimes obscure the essence of what you're doing and I feel a lot of times having many years of experience in C# and in Python really the Python stuff is often quite clear. We are missing the type information like do you really know those are integers? Hang tight, we're getting there. We're going to cover these foundations first. Here is generators both in C# and in Python really only major difference is you don't say the return type of function so you don't need IEnumerable<int> as that cause you can't even really say it yet. And instead of yield return, you just say yield. Super similar right?
|
|
|
transcript
|
1:01 |
The essence of a generator both in C# and in Python is to loop or go over a sequence and then somehow indicate here's one, here's one, here's one and the functions can basically run until you say here's an item, it returns it back and then when whoever's consuming the collection asks for the next one, it restarts and runs to that point. Here's the Fibonacci implementation for the infinite series in Python, and the way you do it is you just use the yield keyword. I go through and set the initial state we've a while true and that one line is the implementation of the sequence to generate the elements and we just, after each one, we say here's one. That's it. We can consume it just in any for in loop or by passing it to a list. It's not a good idea to pass an infinite sequence to a list, but if it were finite if there's some reason that would stop, you know it wasn't a while true or there's a break or something we could actually do it that way as well. Basically generating something that is iterable Python's equivalent of IEnumerable.
|
|
|
transcript
|
1:36 |
Ternary expressions are like short one line if statements. So here we have a program that goes around and asks the user to enter a number between 1 and 1000. And then it parses it, and then here is a little if statement that's all on one line. A ternary expression. First has the test, num < 100 if that's true, it's going to print out the first value or execute this command here, small. If for some reason it's bigger or equal to 100 it's going to say huge. And then we just use that to print out The number is small or the number is huge things like that. It's kind of a silly example, but you can definitely see what's happening here, right the idea is just use this one-liner probably it's better in some kind of if statement but you know maybe not in this case. Let's run it real quick just to see what's happening. We can go over here and say 10. The number's small. 99, 98, small. 100 and I'd don't know, 101. It's huge. Okay, if we hit enter, just leave. All right looks like our program is working as expected. So here's the ternary expression, C#. Test? true : false How do you know that it's true and then false and not false then true? You memorize it. That's how it works. There's not a whole lot of obvious reason it's not like if you didn't know about this you would know what this meant, you just have to study it and learn it. Not too bad, it's really good if you like little lambda expressions and stuff that you want to have, just a little test and then some kind of conditional and as an expression and the value comes back, pretty nice for that.
|
|
|
transcript
|
2:13 |
Python also has a ternary expression and we're going to look at it now. So, let's start with our little ternary app here we're going to use my if main live template and it had a while true section in here. So in this it had text like so and it said and then you'd have to test it if it was empty so we can do that if not text print, like this later, and a break. Alright, that's cool. And then the next thing if it was some kind of content, we assume that we can parse it. We didn't have really error handling here so it's fine. We're going to parse it over I'll say the number class is either small or huge. In C# is was test? true expression : false expression. Python takes a little bit more to get used to there's some advantages and disadvantages but it tries to be more English-like. It starts out with the true case. So we'd say: small, then if, then test so n < 100, else false case, huge. Like this. And I guess that would be num. So this right here is the ternary expression in Python. True thing, if test else that. So it tries to be more English-like. Small if the num < 100 else huge. We're just going to print out the number is num_class like so. Alright, let's just run this and see what we get. Alright, inner number 4, small, 100, it's huge! Boundary test 99, small, something huge like that. Perfect. Empty, it exits. Pretty cool, huh? So that's writing this test here in Python. Let's do a quick side-by-side. Like this. Like that, so let's go up to the main there you go. And remember you got to ignore that 'cause that's just in another file in the C# one. So here's the comparison of these two. While true, go through, get the stuff now mile it, parse it here's the test, the part we really care about right here versus that part right there. Pretty cool.
|
|
|
transcript
|
0:39 |
Quick review of Python's ternary conditional expressions. So here we have a number. We're trying to test if it's small or if it's huge. There is no middle ground in this world. And it's defined to be small if it's less than 100. So it's meant to sound like English. Small, if number's less than 100 else it's huge. Pretty straightforward. The one thing I don't like about it is often I like to see the test and then the outcome. I would kind of sometimes prefer C# for that. For other times I find this really readable. Anyway, this is what we have in Python. It's the equivalent of the C-style one that you're probably familiar with from C#.
|
|
|
transcript
|
2:35 |
Lambda expressions were introduced with LINQ back in C# 3.0, in my opinion, they are one of the most important additions to the language along with LINQ itself. That was groundbreaking work they did from C# 2.0 to C# 3.0, so, let's look at that really quick here and see if Python has some kind of equivalent. We're going to take a random list of numbers here list of integers. And I would like to sort them, normally you could just do real simple stuff like data.sort, you'd be done. However, I don't want to sort them smallest to largest I want to sort them some other way or maybe I have a list of customers I want to sort them by their total value descending right so I need some function to pass to sort to say, well, don't just sort by comparing the items directly but apply this change or this algorithm to each comparison so what we can do is we pass a lambda expression here. We say there are parameters n and m. They go to the expression the return value. Math.Abs(n) - Math.Abs(m) so what we're trying to do is sort by the size of these elements, forgetting, whether they're negative or positive, if you could just take away all the negative values and just do regular sort and then put them back and that's what we're trying to do. So we're going to print it out here. That's a little function print collection again. And I'd also like to, you know, maybe do some other stuff like given those elements, I would like to convert that to an collection that is double that double each element in the list, after it's been sorted. We can use little LINQ to objects here, and pass a lambda expression to LINQ and say to the Select function and say, given any element in the list I want you to say the next element is two times that. So let's just run this real quick to see what we get. The first one is the perfect sorting 11 23 that all seems normal till you say 21, -34 55. Notice it's sorting by amplitude or magnitude of those numbers. And then the second one that I pass off to the print using that select statement actually created a new collection that is double the first collection. Interestingly, just like the stuff we talked about with generators and Fibonacci sequence, this is also one of those lazy collections which is additionally, awesome. These are lambda expressions, they're really great instead of writing a whole different function of processes I can literally write this incredibly small bit of code here and just pass it to the select statement and modify the behavior select or sort or things like that really a nice feature of the language.
|
|
|
transcript
|
4:59 |
Let's see this idea of lambda expressions and these little computational, tiny methods that we can pass around look like in Python. So we'll start again with our main structure. And I'm just going to paste in some numbers because these are the same numbers we were working with in C#. And we don't have to write the print collection we can just print these directly and Python will print them. So let's just see that everything's hanging together. Beautiful. Unsorted. Unsorted, but there they are. So, what if we want to sort these? How would we do this in Python? Well, we saw how to do it in C#. We said numbers, nums.Sort Oh that's right the difference is the capital S versus the lowercase S. Instead of passing just an argument we have to do a keyword argument here. So, the key the element that we're actually sorting on for any element in the list it's a little bit different. You don't compare two, you just give one back. So here is where I would have written the lambda expression. In C# I always say, n goes to, What was it? I would say something like Math.Abs(n) Now, Python, we don't have this syntax. We have a better one, not better. A different one. We see the lambda n Well, it sort of triggers here's a function and then from there to here actually it goes there. Sorry. What goes before the colon is the argument. So you could have n, n but we don't need it in this case. We don't have a goes to, we just say this. So here's how we achieve exactly the same thing as we had in C# but in Python. Not bad, right? Let's see that that's true. Look at that. Sorting ascending. There's our -34 right where we would expect it. Perfect. So, this cool. I really like this. This is exactly the same idea as we have for lambda expressions in C#. Big difference though: in C# you have two types of lambdas. You have single line ones like the ones we've been using in the example I just showed you and you have multi line ones where you can use curly braces and actually do work and then return a value like more explicit lambdas. Python only has the one line. So, in comes an argument. On one line you have to generate the return value. That's it. It's a little bit simpler but that's the big important kind of lambda anyway. The other thing was we did the Select statement with LINQ objects using select on an i numeral. That is not something that you can do in Python. We don't have LINQ. That's actually unfortunate. I really love LINQ. I wish we had LINQ objects. But we don't. Nonetheless, we do have some interesting similar types of expressions. So here I could come over here and say doubled. So we're going to create a new collection. This doubled is going to be... remember we had nums.Select(n => 2 * n) Let's go over here and I'll leave that for a sec. What we do is a little bit different here. We say we're going to generate a list so we say [] and we first say the element that we're going to select. So we would say 2 * n, right? That's this part. for n in nums. And if you wanted to test you could say if n % 2 == 0. Like you could do only for evens or something like that. I'll put it like this for you. There we go. In case you want to see what that looks like. And then let's print out doubled. There you go. That's the Python version that we actually previously had done with LINQ objects. This one actually generates a list like if we ask, if we say print type of doubled you'll see it's a list. If you want a generator a lazily evaluated one like you had with this one from LINQ objects you make the slightest, tiniest change you convert this from what's called a list comprehension to a generator expression. Remember the yield from keyword? Well, yield in Python, yield from in C# well, if it's square brackets it's a list. But if you just change this to parentheses then you print type of doubled Now we have a generator and printing it out like that doesn't tell you anything. So you got to loop over it. A quick way to just make this so it prints is to throw it back into some list or something like that. We could loop over it and print it explicitly but you can see the same numbers do come out. You even have this lazy evaluation version like that. If you want to put this in here you got to change that. I'll go ahead and change that to parenthesis to get the same effect, okay. All right, so these are lambda expressions in Python. They always go like this. Lambda arguments if they are None you just go like this. Here, like that and then it goes to a single line expression that is the return value. You're going to find that you can use these a lot in Python.
|
|
|
transcript
|
0:52 |
Functions in Python are first-class objects. You can pass them around, and one way you can define them are through these lambda expressions. So here we're sorting this in Nums, a list of numbers and we want to specify how we're comparing each individual element. So we just create this lambda expression given an input, or argument n, what do you want to do? Here, we're actually going to sort by the negative amplitude if it's an even number and the positive amplitude if it's an odd number. It sorts exactly as you would expect: the first four, five numbers are even so they're from largest to smallest and then it switches to odd so those are all sorted to the end and then from there it goes up, up, up, up, up even though there are some negative ones up near the top their amplitude is, of course like, amplitude 233 is bigger than 89. How cool is that?
|
|
|
transcript
|
3:21 |
I want to talk about another function feature of C# that's pretty interesting. I suspect it's not used that often. It's a little more common in the Javascript space but it's definitely a feature of C#. It's really interesting. It's called closures. So the idea of a closure is I've got some function going to pass some data to it. And then that functions going to create another function here. And that other function is going to capture or get the closure of these variables that were ambient to it. Kind of like globals but only within this function which was only defined temporarily. Then when you execute that function later we're going to return it. When we execute it later its actually going to remember these. It's just like we went and created a counter little method does counting. We created a counter object a Counter class and gave it two member variables. Where does it start? Actually 3. What is its start value and its counter ID. And then each time you call execute or something on it it can work with those values. Same thing here except for not creating a class. It's just a function. So notice this delegate that we're creating has it's void, it has no arguments. And yet it's working with start which is defined right here. So we're working with counter idea which is defined there. And its working with starterVal which comes in here like this. So we're going to call this CreateCounter. It's going to describe what it's doing creating counter with this. Create a function that does not execute. We're just handing it back. But it's now captured that state that is erased when the function returns. So it hangs on to it really funky. So we're going to call CreateCounter with 7 and then an id of 1 and CreateCounter with -100 and an id of 2. We call counter1() it goes and increments 7 to 8. And we call it again down here it goes 8 to 9, 9 to 10. But this one called with different values actually has different like state captured in it. It's different closures. So it'll be like -100 to -99 and so on. So let's just run this and see what we get. Check this out this is crazy. I called a function pass it some arguments and then I called it again and again each time being void and yet it remembers that it's id was 1 it's start value was 7 and it's current value is 10. First 8, 9, and then 10 it holds on to this. It's a really interesting idea of how to pass additional data. It might seem crazy like why would I ever use this. Well, imagine you have a lambda expression and your trying to do a sort and you need to use data. Its ambient to the current scope but there's no way within that lambda function to pass it over like your passing it through the list and the list only passes what it passes. So you can use closure or this capture stuff to actually git additional information or values into these lambda expressions. Alright, really really cool stuff. This is how you do it in C#. All you do is you have a function a delegate in this case could be a lambda expression as well. And all you have to do is just use the values here with you know that come from the outside use them inside and now their captured and held onto forever. And they can even you saw they can be changed right? Like the start keeps getting changed and changed and changed to remembered between calls up here. So that's closure in C#
|
|
|
transcript
|
3:24 |
We saw this idea of closures in C# was really interesting and powerful. Does Python have something like it? Let's find out. Over here, let's create one of these functions that creates this counter, this closure. So, we'll say def create_counter and it takes a start_val and a counter_id. So what did we do? Well, we had a print statement, and then what did we do? We defined a delegate type, didn't emphasize that we had to create a delegate type and then we defined a delegate instance. Python you have this idea of these delegates as well but it's much, much simpler. You just define a function with exactly the same syntax but indented so it's defined here. We'll create a counter, which is a void function say has a start, equals a start_val it's going to start from that. Maybe, it's going to increment. We called it start before but it's kind of badly named so we said every time you call it we're going to increment this by one, and then we're going to print out some kind of formatted string. Like this, we're going to say the current counter_id is this and we started at this and now our current value is whatever we've incremented it to. Notice though, there's something a little bit funny going on here. We have these values that seem to be captured just fine but this increment, there's something off with it it says we don't know what that is. And in order to tell this function it's allowed to capture local variables or even just to try to print it out you have to use a new keyword, a nonlocal inc and that says I'd like you to reach up to this intermediate scope, it's not global it's not defined here, and work with it. Sometimes you have to use nonlocal, sometimes you don't it's not entirely obvious when that is true but down here we can return count, counter not like this, that would call it, just the name. So we're turning this function that was defined right here and it's actually going to do closure on these values just like before. So let's go over here and say counter1 = create_counter, start value and we have 7 and the id was 1. So let's just call counter a few times like that we run this, and we run the right thing. Look at that. Counter with id 111 it's start value is 7 now it's 8, now it's 9, now it's 10. Pretty cool, right? So exactly like C#, except for we didn't have to jump through hoops to specify the return type here of whatever this delegate type that we're going to define we just said no, here's a function really more generally, there's something. Here's a thing that can be called 'cause classes and other objects can implement something along those lines as well and then we just passed it back. We also just had another one that was at -100 and this was id 2, that we said counter2, counter2 and then we did that three times. Run it one more time, okay. Counter id 1, 1 and 1 still goes from 7 to 8, seven to 9, 7 to 10. And number 2 is going from -100 to -99 to -98, to -97, exactly like the C# closure that we had before. Cool, right? So, same thing if you have lambda expressions or those little types of things you can use closure to capture those values into interesting things. But just be careful because these values are remembered they don't reset like normal functions.
|
|
|
transcript
|
0:56 |
Python functions capture data if they're in this intermediate state using closure. So, here we have a function that is creating a function. So, create counters, creating counter the function and counter can capture and remember the variables that were ambient to it while it was created in this intermediate state. So, it can work with start_val. It can work with increment or inc one as we called it. And as I make changes to those they actually remember over time. Counter is a local function that remembers both inc but also the start_val actually just changes increment though which is more impressive. Start_val and inc are captured. But notice that only inc needs nonlocal scope right, the parameters you don't have to do that for but if you have like an intermediate to variable that's defined in the third line here you have to say nonlocal to make that visible to this inner function.
|
|
|
transcript
|
2:06 |
This is a little section that you are going to be very excited about as a C# developer. It's probably been a little funky for you to deal with Python in its dynamic language types and sometimes you're just like, oh, what is this? What operations can I do on this element or why can't I say this is an integer or something like that. We're going to look at the C# type system super quick because I'm sure you know it really well and then we're going to do something similar in Python, surprisingly. So we've got a class, it is a Wizard, like from a game or something and I know normally you would put this in its own wizard.cs file but with all this stuff going on we're like running low on grouping options so I'm putting it in this typing file here, okay? It has a string, which is a name it has a name which is a string, rather it's a level, which is an integer and it has this factory method called Train. You can pass in a base level and out pops a wizard that is trained up to that level. Not a lot going on there, but whatever. And then here's the main method. We're going to create a wizard, we're going to call him Gandalf and we're going to level him up a little bit and we're going to say the level of the wizard is whatever their level happens to be, okay? Run this. Awesome, the level of the wizard is 8, and it started out as 7 and obviously it compiles and runs. So this is just a real simple case of working with types, right? We have a wizard class, we say dot, we get Train. Obviously if we can explicitly state this is a wizard and everything works, but if we tried to say it's an int obviously not so much, right? Not so happy. If we try to change this, obviously you can't just leave it void or whatever, right? We have to say either var, where it implicitly adapts the type that is returned here explicitly a wizard, or we have to say it's a wizard like so, right? And once we do that we have all the type options, name and level and things like that that are a part of this class. That's C# typing, and let's just run it one more time to make sure I didn't break it, 'cause it compiled while I was fiddling with it. Great, Gandalf is level 8 in C#.
|
|
|
transcript
|
7:37 |
If you've been longing for types, somewhere, somehow in this code, to show up and say, you know this next it's actually an integer or the return value of this thing is a list of numbers or something like that. Well, since Python 3.4, we've had the ability to specify types, much like Typescript for Python. Typescript lets you optionally add types it's a little more constrictive than what you'll see in Python but you can either run plain Python or you can have Python with types these days in Python 3. So we're going to explore that, and this Python with types, in a limited degree, is actually the kind that I like best. You'll see that some parts of your code don't need any typing and some parts it actually benefits them a lot and lights up the editors like Pycharm and VS Code and so on and it's totally worth it. Now I know we haven't yet gotten to classes and we're going to focus more on that in a little bit but I'm going to use a class here so we can have a type to find here, okay? So, if a little bit of the details of the class are vague, don't worry about it remember next chapter we're diving into classes deep. So what we're going to do here, is we're going to define a class which is a wizard. Let's remember what the C# one had. We had a class which is a Wizard and they had a string name and an integer level. So, for Python classes we go to the constructor to define the fields not necessarily at the top level. Can do it at the top level but we're going to talk about that later. So we have not a constructor method or a wizard or whatever we just have a what's called a __init__ double underscore init and down here we don't have a this we have a self, so we say self.name = let's put a W for the wizard and self.level is going to be equal to 0. And then what do we have over in the C# world? We had a static wizard method so let's go over here and define a train method. And it's going to return a wizard and this is going be a staticmethod. Right. That's what it was before. In C# it was static goes there, in Python it was here. We'll talk again about that in the classes and what we're going to do is we're going to create a Wizard. This is like new, but you don't say the new keyword. Then we say let's set the base level here which is an integer as we'll see. Notice there's a level, right, got dot level so it's understood this is this type but it doesn't really have the typing yet, it's just the editor's being really smart. And, yeah, let's just say, we're just going to leave the name alone, some wizard, I don't know. We could pass this in but the one we did in C# didn't have it so let's just leave it like that. Alright, so here is the definition of a class that is almost like the one we have in C# it has a name and a level, it has a train method and it returns a wizard. Did I actually return it? No. There. Now we have like what we had in C# and we don't want this self method for a primer for static methods. Okay super, so this is looking pretty good and then we had this main business down here. And what we said is that Gandalf is a Wizard.train set the base level of 7, over here it's going to be 100 and then we print it out that something like the wizard is some level, I'm going to say gandalf.level, like so. PyCharm thinks this is misspelled of course it's not, right? Alright, so let's run this and see what we get. Does it behave? Excellent. Oh, it didn't level it up. Right, that's the other thing we did. We said gandalf.level += 1. Now it's 101. Perfect. That's what we expect. And you might be wondering, okay, well I guess there's a class but where's the types, Michael? They're not here. Yet. This is the untyped version. But Python, like I said since version 3.4, we are on 3.7 you can see down here on the right, since 3.4 you can define types. Actually it's a rich typing system that describes. So I can come over here and say, in C# I would say something like string name or in Python's types I'd say str name. That's not how it works here. It's more Typescript like. You say the variable and then the type, so name colon str and name colon int. So now when I go over here and I say dot level dot, notice it's offering auto complete for integers. How cool is that? Okay. So it knows that this is an integer and down here I can go to this method and say this method takes an integer and then it has a return value which is this arrow here like that and we're going to return a Wizard is what you want to say. There's a small challenge about the way that the parsing order happens in Python so when you're talking within a class that it returns that class, you have to put this in quotes. But notice it has it like colored to say no, this is a special thing, not just a string. Okay? So now if I go over here and I could work with this. We could say this is a wizard and then gandalf dot name obviously it knows that's a string but if I said this is something else I'm defining it to be an integer it gives you a big warning and says no, no, no you can't assign a wizard to an integer and down here it says the integer doesn't have a level. What, are you crazy? Right, so you can either omit this and it probably can figure out that that's a wizard you can see it's doing this here. But if you want to be super explicit or some reason it doesn't pick it up, you can say this is a wizard. Double e here right or for some reason this method didn't say what it is but you know what it is go like that. So check this out. We have Python with types. Try it again. It works fine. One thing to notice though, this is like an editor helper type thing. If this is an integer in C# this would crash. Here it just keeps running, right? You get this warning in the editor but you don't get runtime validation. Rarely, not never, but rarely does the typing information actually get taken into account. For runtime it's for continuous integration tools and linters and definitely for editors like Pycharm and VS Code. So that's a real big difference. But you can have types. Now, one more thing we want to do here. Why would I give this name as always some other? That's weird. I could just set it to be none and then people could specify what the level is, right? Now notice there's an error. In C#, strings are reference types. In Python, everything is a reference type. Everything. Even numbers are reference types. In C# world they should be able to be set to null they're None in Python, right? The type system is more specific and it has special handling for things that can both have a value and be none. You have to explicitly say this is a nullable string even though it's a reference type. So notice here, does expect the string got None. So what we have to put an optional string. What is optional? This is defined in a library called typing. The top, run typing, import optional. Now, our none error went away. Right? We could do the same thing if we didn't want to start with a zero value, we could have an optional int set to None. Let's run it one more time. The wizard Gandalf is at 101 with all sorts of type validation in Python. I think that's pretty cool.
|
|
|
transcript
|
1:19 |
Using type annotations or type hints that kind of go by these two names in Python is super, super useful. The bigger your application gets the more help you want your editor and other tooling to say, you know what? That is a Wizard or that is a string or that's an optional string and you're not checking it for None and things like this. As of Python 3.4 we can have types in our Python code. So here, for example we have wizard class and its constructor. It defines two fields, two public fields which are an optional string for the name and an optional integer for the level. And they're both set to None. Using the Optional[str] Optional[int] defines those types. Then our train method takes an integer base level and returns a Wizard. Because Python parses and defines these types all at the same time it's not until the end of this whole code block that wizard is defined as a thing. So, we have to put wizard in quotes only within this class. The rest of the application we just say wizard no quotes treat it like a regular type. There's this little edge case here. The newer versions of Python are working around this have better syntax. But, you know, it's not a big deal and I want to make sure this is like broadly applicable today and not just in the future. So, "Wizard" at the end here.
|
|
|
transcript
|
2:31 |
Let's look at a program that's not very reliable so it's going to need some error handling. Here we have our run method for the Errors class and what it's going to do is it's going to generate a bunch of numbers 1 to 20 and it's going to add, I don't know some Fibonacci numbers or something like that on the end. And then it's going to try for each one of those numbers to call SketchyMethod. The name might give you a hint of what's happening here. So it's going to set the color to gray so you can see what's going on really well and then it's going to set it to yellow and if there's an error based on the error it's going to say cyan and then some kind of message. So here's error handling in C# we'll call a function and a try block. And then we can distinguish between the different types of errors by having different catch blocks. So there's a SocketException. We have catch(SocketException). There's a ValidationException like some value is not valid we'll get it down here. If it's some unknown Exception we can just catch it in general and to find a variable which will not appear and we're going to print out oh, there's some kind of error we're going to get the type say it's this type of error and here's the message We were not really planning on this but something bad happened Pretty cool, let's run it and see how that works There you go, you can see we didn't have a lot of faith in it so we run it, and it says calling it with 1, hey that worked, 2 that worked we call it a 6, for some reason, we got an overflow or underflow arithmetic exception, right? This was one that got caught down here we didn't expect it, so we just printed out the type in a message Down here, we've got a network error that was a socket exception that was thrown We said there's something wrong with your connection It worked for a while, network, and then arithmetic and then lets see In this one, we pass it 0 and it said no, no, no, I can't work with 0 that's not something I can compute with Okay, so here's error handling in C# couple things to note, try, do stuff, catch But the catch has to be most specific down to general Because the way it works is the error's thrown and C# says, does it derive from SocketException? If yes, we go here. Otherwise, does it derive from ValidationException. Otherwise, does it derive from Exception Finally, yes everything derives from Exception that can be thrown, so down here we are handling this So, you've got to make sure that you have it more specific to more general the way it goes down here, all right This is our super reliable way of working with this SketchyMethod
|
|
|
transcript
|
6:08 |
Let's see the error handling here in Python. First of all, we're generating the same set of values. We're getting a list out of this first 1 to 20 numbers and then we're adding on these additional values here like so. So really nice and we're just doing one line here instead of 4 or 5. We're going to loop over those values. I'm going to call this sketchy_method. In the moment, we're not doing any error handling whatsoever so you can imagine this might not go well. Also notice up at the top we have something called colorama and this allows us to set the foreground color and so on for our output just like we were console foreground and whatnot. So in order to install this we have to install this separately. There's a couple of things we can do. We come over here and have a new text file which is a convention in Python. We'll talk more about it later but just so we have this listed somewhere. So we have something called requirements.txt and the tooling knows about it. So if I go over here and just I put colorama notice immediately, PyCharm is like whoa, whoa, whoa. Colorama is not satisfied. We need to install this. Where is it going to install? It's going to install it into our whatever virtual environment is active there. So it's going to install to this one. So we could do that manually or we could let PyCharm do it. So I'll go ahead and just let PyCharm do it. Boom, it's installed. It's still got an underline but that's just 'cause it's misspelled. I'm going to say no, it's not misspelled. We come back here, now this works, okay? So now we can do, like, Fore.yellow, blue, whatever. All right, so let's run this program here and see what we get. Well, it worked for a little while 2, 3, 4, 5 and then it looks like the error happened earlier but it actually happened at the very end. It's just the priority of the system error output stream is higher than the priority of just the regular output. So it comes out of order, right if we don't flush things and so on but ignore that, right? It ran for a while until it got to 6 but it didn't actually work. It crashed and we got an ArithmeticError. Okay, so let's start adding in the type of error handling we had before. Remember with C# we had try and catch this, catch that. So Python has almost the same syntax, try do something. You don't say catch. You say except, like this. You can just have it blank. That probably isn't what you want. But we could print out oops, like this. And let's make it some kind of color. Foreground.red, light red, let's say. Now if you run it you can see oops, oops, periodically. It's crashing. But we can do better. Just like in C# we were able to capture these different types of errors we can say except error type. Instead of catch error type, except error type. Now what we can do is we can put out some message about the type of error that we got. And we could do something like our value here and maybe let's make it really obvious that this is an error, like that. Okay, try again. Cannot compute with 18 because it was an ArithmeticError and we got another one which is a ValueError. So we're going to get some of these random types and we've done the studying of this sketchy_method and we've realized that there's a couple of types we can catch types of errors we can deal with. There's a BrokenPipeError and this'll be check your network. Check your wifi, okay? We could get an ArithmeticError and then there may be other ones that we're not aware of. So down here we can just say except Exception and we can print out, let me just copy this. Print out something like this. So when we didn't know what we were doing before like when we didn't know what the error type was we said error and we have the type name and then the actual problem. So in order to do that we actually need to capture some sort of variables. So you don't say exception ex. You would say as ex, right? This is how it works. And what is this unhappy about? It just says too broad. It wants us to catch more specific stuff. Alright, so now we come over and we could print the same type of thing. So we'd say give me the type of ex. And under name, like this that's the type name there and then we could have some kind of thing like what is the error. Just the string that's this is the way you do to string on an object in Python. And let's space it out a little and run it now. Nice, look at that. So we got exactly the same error. We got a cannot compute a 6 and a network error cannot compute with 12. Oh, let's see down here what we have. Oh, this is one that was unknown. It's a ValueError. None apparently is not valid. So when we didn't specifically handle this as an exception case we were able to catch it and do something kind of meaningful with it, I guess. And then the rest of it, that worked. Pretty cool, right? This is actually super, super similar to C#. Let's go and do this side by side again here. Oh, that whole bit of screen there is the C# one. From here to there, that's the Python one. We can see it's the same basic structure for each, or for in and then try do the block. Try do the block. And then either except exception type or catch exception type and then you just deal with it. If you want a variable, the you define the variable either like this here or as ex over here. Beautiful. This should be really, really familiar to you there if you've worked with error handling in C# it should be super comfortable. And there's also a finally in both. Obviously there's a finally in C# that you probably know. There's a try finally so we could add a final block here. Finally, you know, one colon, print. Finally, whew. So you can see there's a bunch of finallys coming out now. Alright. I'm going to comment that out 'cause it kind of messes it up but I'll leave it in there as a comment. So try except finally versus try catch finally.
|
|
|
transcript
|
0:43 |
Error handling in Python is quite similar to C#. We have the exception throwing type of behavior when we say try, do the thing instead of catch we say except and we don't have parentheses but, pretty much other than that it's more or less the same. The one thing you need to keep in mind also applying Python is this goes from most specific to most general. It goes through and says Does the error derive from the thing you see in the except clause? Like, the exception I got, does it derive from BrokenPipeError? If it does, run in that bit. If it's an ArithmeticError something deriving from that go in there, and so on. So, just like C#, has to be most specific to most general or it's going to get caught too early.
|
|
|
transcript
|
0:54 |
One of the beautiful things about the C# language is the using statement. Here we're creating a text file a stream writer, that we're going to write to this JSON. So we're creating a dictionary and we're going to store the dictionary by serializing it into that file, and it just says, hey, we created this file. While we're in this block, this file is open and ready for writing. Here, it is closed, and flushed, and done even if there was an exception, it's all cleaned up. Beautiful, right? Let's just run this real quick. Alright, it says it created a file let's go have a look, see what we got. That would be in bin/debug on that core and down here you can see here's our file.json with Michael and the language is C#. Pretty cool, right? And of course that was created safely using the using block.
|
|
|
transcript
|
2:55 |
Would it surprise you to know that Python has its own using block? They don't use the keyword using, they use the keyword with but it's very, very similar. In fact, even the things that can go into the using block have to implement a certain method or interface type of thing much like you have to implement IDisposable in C#. So, let's get started with another program here. This one we're going to use the json library. In the C# version we use in json.net Python has a nice built-in json library so we'll just import json and we don't need to add it to a requirements file or anything like that. And over here we can create a dictionary we'll call it data. And the way you create dictionaries in Python is just use curly braces. This is one of the use cases for it. And we'll have a name name is Michael, the language is Python. Okay, super, I want to save this using the json library save the data into a file using the json library, super easy. So we're going to create Python's equivalent of using block, we use the with keyword. And then we're going to create the thing new up something, but for files you just call an open method, and you pass the file name. So it's going to be file.json, I think is what we called it. We want to write to that file and we want the encoding to be UTF-8, that's usually a good choice. This creates the object and then we're going to define a variable to work with it so I'll say fout, for file output stream. This is like a using statement with thing as variable. And then I can go to json and I can say dump to a file, it's kind of annoying. The terminology, I'd like save or write or something but this is the way it goes, you can pass the object and the file pointer. So the object is data, the file pointer is fout. We're done, that's it. I'll say print. Save to local file, file.json. Ready to see if this works in Python? You can bet it will. It ran, it saved to a local file. I noticed over here we now have this file. Beautiful, right, how cool is that? And we could even make it prettier, we could go over here and say, indent equals true. Now if we go look at it's slightly more formatted and so on, but that's not really the point. The point is we have this same idea as the using statement in IDisposable in C#. This is technically called a context manager. If you implement the right interface as we'll talk about later when we get to classes then you can use that item here like this. You can also do it without defining a variable. It could be that if we didn't have to actually refer to the variable, this'll be fine as well. But because we refer to it, it was like that. The warning here is just that it's quote misspelled. We'll fix that problem. Awesome, looks like our file got created here and everything's golden.
|
|
|
transcript
|
1:24 |
Python also has a using statement. It's called with and the syntax is super super similar. with. Create the item as the item name or variable. Just use with. It's really really nice. It's like Try, and then finally enclose or dispose but it's even better than C#'s. Why is it better? Well with C#'s, using statements using a thing and then that thing in the end even if there's an exception it gets disposed called on it, right? IDisposable, that sort of thing. With Python's version when you implement it behind the scenes like you do not see it happen here but if you created a class that was able to be used in this context the finally closed part calls the close the right time even if there's an error but it also passed to that class that's being used in the context manager whether or not it ended in success. So when it closes it or it calls the finally disposed type of thing it passes, here's the error, here's the exception or it passes None, null for that value and you know whether or not when you're disposing it whether it's success or false. Imagine IDisposable took a nullable exception type that was part of that when that when that function when disposed got called. That's what Python is like and it's really nice. Super cool, you can implement a ton of fun stuff. This and plug it into these with statements.
|
|
|
transcript
|
0:56 |
When you have a conditional situation with lots of different options lots of different possibilities you don't necessarily want an if else if, else if, else if else if all over the place. Switch is probably what you want. Now you can't put everything under switch but a lot of times if it's a direct comparison in quality it can go in here and that's pretty sweet. So what we're going to do is we're going to have this program that loops around. It asks you to enter a number between 1 and 4, verifies you entered it and then it's going to switch and then based on that it's going to do a Console.WriteLine and break okay. Let's just look at that real quick. Super simple switch statement. I could put 1 it says 1 is fun. I could put 4. 4 more, 3. 3 and free. If I could put 72 it says no 72 I don't know what's up with that. That is of course the default case. Say what number? I don't know what to do with that. Finally, if you hit it, enter it goes away. So here's how we use switch in C#.
|
|
|
transcript
|
6:11 |
Now let's see switch in Python. This should be pretty short because you know what Python doesn't have a switch statement. Literally the language does not have a switch statement. Like, it does not have a numerical for loop like for i = 0, i < limit. There is no switch statement. There's only if, else if, else if, else if. So why do we even have this part of this chapter? Because Python is super flexible and we can build our own. In fact, what you just saw this using statement this with context manager is all you need to actually build your own switch statement. And let's look over here. I did. I created this thing called Python switch over on my Github. It's public. You can play with it. Do what you want. It actually shows you how to do that context manager stuff I talked about. So let's create a new program here. What we had before was a while true we've got some text equals input enter a number... Like this. And it said if not text print 'later', break. Like that. And then we said num was equal to the integer parse of the text. I think that's what we did in C#. And then we wanted to write switch. Well you can see this is an error. There is no switch statement. Check this out. So we can start using this library this module over here by saying, from switchlang, we need to change this to have that be a source's root. So here we say switchlang import switch. This is the switch statement that I made for the world and down here, the way we're going to do it is instead of saying switch value, case, case, case, case, case we're going to use a context manager to say with switch(num) as s: Looks maybe a little bit weird but I think let's roll with it for a minute. I think you'll like it. So we can go, s.case instead of saying case: or the value:. We can just say the 'key'. The key is going to be like 1 so we'll link this really closely. Case 1 is going to be case(1) and then you put a function colon here. Like a lambda. This one's going to do nothing take no values. And it's going to print out exactly the same value we had in C#. One is fun. Okay, that's cool. Let's do Case 2. Let's put it and see what it said right here. So 2 times 2 equals 4 which is fun. That was that one. This one said 3 and free or they've got a period is 4. Four more and of course the case was 4. Now by the way, if I leave it like this and I run it right now I put 7 It doesn't matter what I put. It says duplicate case. It checks that you just like the compiler would check that you can't have Case 3, Case 3 this thing checks, like that. Then what did we have before? We had a default. What happens when there's a default? There's a lambda, and the lambda prints. Say what? And the value over here was num. This, by the way, is using closure to capture this value. It seemed not useful, and heck here we are in this trivial little case using it already. Let's run it and see what we get. Number 1, one is fun. 2 and 2 is 4. 3 and free, four is more. If I put 72 or 74, say what? 74. If I put enter, later. Now that was pretty incredibly easy to write. But this switch statement is actually more powerful than that. It accepts ranges and other stuff like that. So there's another thing in here called a closed range like that. And I could do something like, here. I could say I would like to have a case that has a closed range from 10 to 20. This matches all 10, 11, 12, 13, 14 and so on and other types of comparisons could be put here and instead of having this necessarily do an action it could actually return a value as part of this switch as well. So we could have it return the function return value. We'll just have whatever the number is, squared. That's going to be the return value. Of course, this could be more complicated based on inputs and all that. And at the end, outside the context manager we could print done and got. Let's see. It might not always do it but sometimes you might get a result. Let's run it one more time. One, got none, that's fine. Two or three, got that. But if I put 12, I should get 144. Done, right? Also we get 11, it hits that case. If I get 15, it hits that case. If I get 21, it's out of that case, right? Don't know what to do with that. Isn't that cool? Here's a really, really clean way to do actually more than C#'s switch statements can do. Okay, so pretty sweet. Actually maybe they support ranges now as well but there's a bunch of interesting stuff that we can add to this switch statement. 'Cause it's not part of the language. We control it. Alright, side by side, let's see what we've got. Does that even fit on the screen? Not really, sort of. But in our version over here of course it fits on the screen. Look at that. Look, it's a little bit weird but if you look at this switch statement it doesn't have the cases and stuff or the return value it's not bad, huh? Remember, Python doesn't even have a switch statement. But I added this to the language because hey, I thought it needed it. I use this for lots of my programs for super gnarly code and it really is valuable, right? It catches errors because it makes sure you can't have two branches that might do the same thing which would have been okay in say, an if statement or something like that. So really, really nice. I love the way this works. I make use of it when it makes sense for like a switch statement in the language. But we just had our own definition we created here and used a context manager to make it work in Python.
|
|
|
|
47:34 |
|
|
transcript
|
3:06 |
Let's talk about object oriented Python writing classes, inheritance, creating objects modeling things like, well, you are probably pretty used to from C#. It turns out that Python has excellent class inheritance object oriented support. So, let's talk about some of the features that Python has. Everything is an object. Now, you can sort of say this also for .NET or for C#, everything is an object there as well. Everything derives or can derive from System.Object That's almost true for C#, because you have value types and reference types in order to treat the value types as an object, you have to box them and unbox them and there's some complications in there. In Python, truly everything is a reference type. Even the numbers are reference types. And all of those reference types derive from the object class. We have instance methods and we have static, also something called class methods. These kind of behave similarly. just like we have in C#, you can create an instance of an object and it has its behaviors or the type has, like, static behaviors, got that, properties. Remember the days when you used to write get value and set value because you needed validation or these values were computed, or something like that. And C# added properties, which is great. Python also has really good support for properties. If you want to hide data, that is, like, private data within your class, Python doesn't have the keywords around public, private, internal, protected, those kinds of things. But, there are several levels of mechanisms in the language to have private data within your classes. We also have inheritance. In fact, Python has multiple inheritance which is usually, actually doesn't even appear. Sometimes it shows up, sometimes it gets used, but it's actually quite rare that multiple inheritance aspect of Python's OOP shows up. But there's a rich inheritance structure, like you have in C#. We can overload operators and we can overload methods much like you can change what equals means, or what hash means, or double equals or divide in C#. We can do the same thing with our Python classes. We can implement special interfaces. Either this can be deriving from a class and doing something like that. Or, there's a whole host of these special methods that are like IDisposable. Remember we talked about with and the compared to the using block. There's a set of functions you implement, you effectively implement the usage within that with block. It's not technically an interface, while it's in quotes here, but the outcome is the same. You also have abstract methods and abstract classes. If you want to create a base class, you can't create an instance of, but you can use it as a base class totally supported in Python. So, you can see, there's a lot here. This is not just some little bolt-on thing or it's not that it doesn't exist. OOP in Python is proper object oriented programming. We're going to go build some really cool classes and model a particular environment and put them into action.
|
|
|
transcript
|
3:46 |
Before we get to the Python version of our object oriented programming let's look at the equivalent over in C#. What we're going to do is we're going to create a hierarchy of cars. Regular cars, sports cars, electric cars. So here we have the car class and this is meant to be only a base class. So it's abstract. And it has some auto properties here: model name, engine type, cylinder, and base price. Those are all passed in to the constructor here like that. It also has cool little property. It'll tell you if it's electric, true or false. And that is to just obviously check whether the engine type is electric. There might be better ways with enumerations and other stuff to do that but we're just keeping it simply here. Just use strings on this one. Then we're going to ask the car to drive. And the default car will just print out the minivan goes vroom or something like that. And then all these, I put the base class here or the class, the type name that's this implementation is coming from. You can put dispatch together. We'll do it in Python. You can compare. They're similar but maybe not exactly the same. That's just drive and it's virtual so it can be overridden. Right? For example, the sports car over here might want to change what drive means. Then, there's also the ability to refuel. And because we have both electric and gas cars the base class, it just has I have no idea. I got to throw up my hands on refuel. It's so different what that means. The class that derives from me is going to have to figure that one out. Right? So when we derive from this for example, the sports car it must implement refuel if we want the sports car class to be able to be created, instantiated. Let's just look at one of these or we can look at the electric car real quick. This one simplifies the constructor. Takes the model name and the base price but it doesn't pass the number of cylinders or whether its engine is electric. It uses the base a delegate to the base constructor for that. Okay? So it just passes through the model name and the base price, but the other two these are set by virtual the electric car. It overrides refueling. With the electric car, like I said it says the type name at the beginning just for this example, so the whatever is charging up and then we're driving, it overrides this as well so we can create an electric car and says the whatever it is zooms silently along. We also have a parking lot over here. And we can create a parking lot using a factory a static factory method. Give it a number of spots, like I want Three levels and five spots, so we're going to create 15 parking spots on each level. Return those. I have some iterator stuff going on here. That's pretty cool. We can get back how many spots are taken. And we can park the car into one of these spots. So we can loop over our spots and then figure out, no one's parked there and we're going to park our car in that spot. Simple data structure, just dictionaries and so on but that's what we're going to do in this particular thing here. And last but not least, we can run it. I'm going to create some cars. We're going to loop around and ask them to drive and fuel and then we're going to park them. So I'll just run that real quick. Boom, hello C# cars. The sports car, the Corvette, tears along the highway. And then it only wants the best gas. And then we create another one. A Windstar minivan, it goes vroom. Cause this one does not override the base class. It's a basic car. But it must implement fuel, so it will take any old fuel. Electric car, zooms along silently, is charging up. Volt zooms along silently, is charging up. And then here's a bunch of free spots. We park a few, and we have The Corvette and the Windstar and the Tesla and the Volt they're all parked in these very spaces. All right, this is our world in C#. We're not going to create it, it's already created for you. Our goal is going to be to explore these ideas and create something similar to, or as similar as we can in Python.
|
|
|
transcript
|
6:16 |
We saw the car class in C#. Let's go create the same thing in Python. Over here, I'm going to have a program just going to start with that. And then in the C# world, we had a directory called models. And over here, we had a class called cars, car. I think that's what we called it. We're going to run this so we can get that set up up here and it's going to work with whatever we define in this file here. We can break the classes up into one class per file. We can have it all crammed into a single .py file if you really wanted to. That's sometimes done. I'm not a big fan of it but there's nothing in the language that says one class per file or anything like that, right? It's very free form. Remember in C# we had a class and it was a car like this. So in Python, we write literally exactly the same thing. The naming convention is also similar capital C, camel casing. We had electricCar earlier, like this. So also similar convention, when you derive from something you would have the base class like that as opposed to in C# it's like this, okay? But pretty similar and if you don't put that you derive from object use still derive from object, also like C#. This is how we define that there is a class and instead of these curly braces, as you would expect we use colons. Here's where you're going to see some differences in how you define types. In C# if you have a field or a property it always gets defined up here. Like you would have an int cylinders something like that, right? And then down here, you'd have your constructor. In Python, it's a little bit different. You can define the fields or properties up here but it's typical if you want just instance fields and you don't want them in the static aspect it's a little complicated. You define them actually in the constructor. So we're going to define a constructor and just like methods or functions outside of classes methods inside classes you start with def and then the built-in stuff always starts with double underscore. So we have double underscore init or add if you want it to act like a list or asynchronous iteration if you want to work with async and await and do iteration in there. So the one we want the constructor is __init__ for initializer. And what did we have before? We had something like model name, engine type cylinders, and base price. So that's what we're going to have and now what we need to do is we need to create a local field. These are just this method. What we need to do is create a field in this class. So we don't have this, we have self in Python and it's explicitly passed, right? C# implicitly has these arguments pass for this. Python is very explicit. We're going to go over here and say I'm having a model name and that's going to be equal to model name. Obviously it could just be model. Those don't have to match, but there they go. We're going to go ahead and make them match 'cause it seems to make the most sense. Now, PyCharm is nice. It'll say, hey, you're not using this. Do you want to add a field to this class? Yes, I do. And it'll give a chance to rename it. We'll do that for the others. We also saw Python supports types. So we could come over here and say this is a string. This is also a string. This is an integer and this is a float, for example. And probably even more valuable is to do that here on these this is like defining the types for the field. So now later if we say self dot, you know, baseprice dot notice all the operations are coming from float 'cause hey, we know it's a float. So here we've defined a class. It's called car. And we can create it with these things. Let's go over to our program really quick. We'll just say cars = create_cars(). We'll write a little function down here that's going to do that for us. And it can return a list and we can come over here and say I want to create a car. Now in C# you would say new car, like this, right? In Python, the new keyword is omitted. We just say car and call it. Now we have to import it up there. And I noticed first of all it's saying chapter four models car car. I want to create the stuff that's contained inside this chapter as if it was just its own program so we don't have to say the full name. I can go over here and say mark directory as sources root and then it says okay. That's like the top level. We're not going to talk about it. We just have models car. PyCharm will write up the top for us from models.car import Car. And that let's us write some things here but notice it says you are omitting some stuff. So we can ask, what is the model name? Let's go over here and say Corvette. What is the, what's next? Engine type is gas. Number of cylinders? Let's say it has 8. And its base price is $50,000. Now, we could write it like this but Python lets you put a little comma digit grouping thing in here and that's really nice. And let's put a few more. Alright now, we're getting our cars here. Let's just loop over to them real quick. Just print out car. If we just print it right away it probably won't give you the outcome that you're hoping for. Oh look, there's a car object at this address. Let's print out something like the model name and car.price, base price, or something like that. So there we go. We have Corvette 50,000, Winstar 20,000, and so on. All right, so that let us define a basic class in Python. We just defined class like this create a constructor either pass in values or just compute them from somewhere else and we create fields by saying self.whatever in the initializer. Notice back over here, when I say car dot it knows it has exactly those four fields car, car, car, car, right? It has those four fields because that is the convention in Python over here to create a private instance field over here exactly like that. So the tooling obviously knows how to surface that back to us.
|
|
|
transcript
|
2:23 |
Well, our car is interesting. It has these properties, right. We saw that it has base price models cylinder and engine type. But you can't really do anything with it. We can construct one through its initializer but classes typically are valuable because they bundle data and behavior together. Right now we just have data. So let's go and add a method here. So again, we're going to make the method part of the class by just indenting it within the class. And then we're going to say def and we have two methods we want to define we want to define drive, and we're going to define refuel. Now watch what happens when I close the parenthesis here or open it to start defining the parameters. As I open, notice it, PyCharm, automatically types self. Because this is an instance method it can only be called if it has this explicit self parameter. That takes a little bit getting used to but it's not hard, it's just different, okay. Then down here we're going to have a little print statement. We're going to say the car, say this is from the car the whatever, self.model_name goes vroom and let's tell PyCharm that is not misspelled. We're going to have another one refuel. Same thing we have our self here and we have a print statement. Actually on this one, let's just pass for now. Remember this one is going to be the abstract one that we don't know how to deal with. Say it's blank, this is like the equivalent of just empty so I use the word pass. I know something has to go here for this syntax to work but I don't care what it is, ignore it. Go over here and instead of doing this let's say car.drive and notice it has this function here. And car.refuel, okay. Run it again. Yay, the car, the Corvette goes vroom the Windstar goes vroom, the Tesla goes vroom the Volt goes vroom. Not super accurate, or really interesting but it does work, right. Our cars are driving and they're refueling and let's put a little new line between them. Cool, so we've got these methods that we've created over here and, right, we saw that they're super simple. just define a regular, like a function has the self as the first parameter. If you don't put this there, if you put a, b, c notice it's yellow and the others are not and this is usually the first parameter is self. You might be forgetting that you've you might want to put something there. So the tooling does help but you got to remember to do it.
|
|
|
transcript
|
2:01 |
This refuel method, remember our assumption was the base car because we have electrics, gas, maybe diesel cars we have no idea how to fuel this car. It's up to each individual car to figure out how it's fueled. Well, we're going to have some classes that derive from this, as you already saw. But what we want to do is we want to make sure that you cannot explicitly create this, but you have to create a fully formed specialization of car. In C# we saw that we could write something like this, like abstract car, right. We don't have this concept of public so maybe we could write this, mm-mm, it's not looking like it, is it? So Python has a perfectly fine way to deal with this. It's just not through keywords, it's through inheritance. So what we're going to do is we're going to use a module called ABC, so I'm going to say import abc for Abstract Base Classes. And here we're going to say abc.ABC. Kind of wish the naming was a little more explicit there but abstract base class. So this is cool. Down here we're going to say this refuel method is an @abc.abstractmethod. This syntax here is new, I don't believe we've talked about it before, it should remind you a little bit of attributes. It's called a decorator and it serves a lot of the same roles as an attribute does. It distinguishes the thing that has got the decorator on it to make it behave differently or to indicate that it has different behavior but it's actually implemented super different than typical attributes in C# are implemented as. Those are like compile-type things. This is actually something that runs an extra function that modifies how these behave. We just put this on here and if we try to run this again it says, No, no, no, you cannot instantiate an abstract car method, a class with the abstract method refuel. Alright, so that's done what we've achieved. We can't create a car, now we have to create specializations that implement refuel.
|
|
|
transcript
|
4:31 |
So let's define some other types. We saw that we can no longer use car directly 'cause it's an abstract idea. It's the base class we're going to use for our program but we want to have specializations that really implement the details. So let's create a new file here called basic_car something like that. Bring another class called BasicCar like so. Now it needs to derive from Car so we want to write just Car here and PyCharm says, well looks like you don't have a definition of Car on one of these two lines, so I have no idea what this is. But we can import it up at the top. We say from, models.car import Car. And then down here, we can put nothing for just a second and PyCharm says we need to implement some of these abstract methods like refuel car. Cool. So it's just going to go here and write this function which right now is empty. Not super interesting is it? But we can print out something like this. Put the type name here so it's really clear where that detail's coming from. The basic cars take any old gas. Right, that's good. Now here, let's see, this is going to be a BasicCar. And again, to use that, up at the top we don't have the right import statement. PyCharm will add it. Or you can write it yourself as we go up a little bit there you go. That let's us do this part here and if we only do that one car, it works. Look, the car part deals with the drive and the Windstar goes vroom. The basic car deals with refueling and it says it will take any old gas. Super. So that gives us our basic car. Let's do a couple real quick here. We're going to define another class, sports car derives from car, just like before we add the import statement above. Now it's going to pay some print statements. So we have the sports car does the such and such tears along the highway, and it only wants the best gas. That's true. Let's also add an electric car. Once again, import the base class implement the two functions, in this case. This, what can I say, the electric car zooms along silently as it has to change the behavior and the refuel one, we have to implement and it's charging up. One thing to notice about the IDE here check this out on the left. Click on this, it takes us back to where it's being implemented, where it comes from. So drive, we see, did it say? Overrides this method in car. Same here. But if you have a rich hierarchy like Car, BasicCar ElectricCar, ElectricSportsCar, whatever right and you're overriding at different levels it will tell you, then also when we're here have the reverse. You can see who is implementing this can see BasicCar, SportsCar, and ElectricCar all implement refuel and you can jump back and forth between them. That's pretty slick. Right, let's change the thing for creating here. This will be a SportsCar and import that. Let's make that SportsCar there like so. This will be an ElectricCar. You can just type E-C and do the CamelCase matching here and get the ElectricCar to come up right away. And up at the top, now we have the 3 that we're actually working with. And now I just remove that in that car there but let's change this real quick and say that this is going to return a list of car. And that comes from typing like so. So this, when we come over here we're going to say cars[0]. and we're certain to get the right things. So we're still using our base type here thing, this is the commonality you can assume across all the collection that comes back but of course, their behaviors are different when we ask them to drive and refuel. Whew, let's try it one more time and see how it's going. Cool, so now the sports car, the Corvette tears along the highway, and it only wants the best gas. The Windstar didn't override how it drives. It just goes vroom. But it had to say how it was fueled and it takes any old gas. Electric car zooms silently along and it's charging up, the Tesla and the Volt. Pretty cool, huh? This is really nice, clean, full-featured OOP and we've got more to come. This is just the start of it. But it's a pretty cool way to get started.
|
|
|
transcript
|
2:22 |
In our C# version, we saw that for the electric cars we didn't have to indicate that they were electric nor did we have to say the number of cylinders which is always going to be zero. We did that by changing the constructor. If we go over to this we can say we want to define a special constructor. And it was going to take let me just rob a little bit from here model name and that is going to be similar. Like so. And we can just do a quick little pass for a second because I want you to see some of the issues or the help that the editor is going to give us. So in C# what we did was we said base. We put stuff here and then we had curly braces like that. Well the colons already used so we're not going to do that. And what we do down here is we can actually say super and get to the base class or super class which is car. We can call it constructor explicitly. That's how you do it. And then what goes in here? Well the model name goes in there. And then the engine type is electric. The number of cylinders is zero. And the base price is like that. So here's how we accomplish the same thing in Python. Now if you try to run it where we create the electric cars that part's going to get unhappy. As you can see I thought we had 3 arguments but 5 were given. By the way, notice 3 and 5 not 4 and 2 the way you probably think about it. But let's jump over here where we're using it. It's part of that self thing. So it says we got some two extra things here. And the two extra things are the electric and the number of cylinders. Both drop that and that. Run it again. Works like a charm. Right so go back here. The way we delegate to the base class or super class constructor, initializer in Python is we call super and then the initializer explicitly. This should always be first. Then other stuff, right. You want it to do all the set up and then make additional changes after that I would suspect most of the time. So I guess I'll leave those comments in here for you. This is how you do it. This is how you call the base constructor and you can have specializations. Notice the other ones just don't even define initializer and they just fall through to the car's definition of initialize.
|
|
|
transcript
|
2:23 |
Properties are a wonderful addition to classes. Older versions of object oriented programming like C++ and Java in the early days you had to have a get value and a set value or a get value if it was computed. For example, here we have a boolean property which is whether or not the car's electric and we can compute that based off of the other information. So here's our read-only computed property, that we can use and then over here we can say car.is_electric. And this is great we treat it like a field, like it's just data and we don't have to treat it like it's behavior. Especially if you're modifying it doing like ++ or something like that. Obviously it doesn't make sense for booleans but you know, if it was a number or something like that. Can we do that in Python? How do we do it? Well, we don't have this get, set syntax but we do have the ability to have a property. Let's do that in the very base car, here. And it has to do with these decorators. So, the way we use a decorator is to change what this does. We also can use a decorator in a shortcut as well to create a method that is actually a property. Same thing that we had in C#. Let's go, right is_electric, now we can compare. It will return self.engine_type == 'electric'. That's it, same thing. So over here we have, going to say this is a read like, this implements the get, basically. The set is a little bit different. It implements something that we can treat like a field or like data, but is actually a method that runs. So let's, over here, and we'll just print out. We'll say, the car.model_name is electric question mark and then we'll just print out this property, like that. And we run this, and bet is going to say you know, False, False, True, True, or something to that effect. Like, Corvette is electric, false. Winstar is electric, false. Tesla electric, true. Bolt electric, true. How cool is that? So just like we have properties in C# exactly the same thing, we have properties over here in these classes. And you define them like this. You say, app property on a regular method. That defines the get. Obviously, it has to be a void method, right?
|
|
|
transcript
|
3:14 |
Time to review creating a base class or super class in Python. Our car class was our super class and we wanted to be abstract so here we derive from ABC, Abstract Based Class. Has a couple of features has a constructor and C# terminology, an initializer or sometimes referred to as __init__(), as in __init__ Though __init__(), you'll hear that a lot dunder methods for this class of methods. And these are the special built-ins like the operator stuff I showed you and so on. So we are going to create one of those and it is going to take whatever data we have to pass to the class to get it started model name, engine type, cylinders and base price. We went ahead and used the typing to make that really obvious. And to define 'fields' by the same names we are going to say self.model_name self.base_price, self.cylinders. Now, we didn't talk about this in the demo but I'm going to mention it here. IF you want this to be a private field use the double underscore at the beginning. It is a weird convention Python is all about the underscores and sometimes they are just separators like base price. Other times they have important meaning. If the underscore is a single underscore in the beginning it's still publicly visible the field or the method that you gave that name but it is indicated, like its you probably should stay away from it. It's kind of an internal thing leave it alone. You put a double underscore the runtime will actually change it's value so you effectively can't simply can't easily without jumping through a bunch of hoops you can't get to it from the outside. So when you say car.__engine_type should not appear. Depending on your editor, but certainly car.__engine_type and working with it won't work from the outside. We also defined a method drive, we're overriding. This one is a virtual, it has the ability to be overridden, but we don't say virtual. Basically, imagine everything is virtual in Python. We have a property we used a @property decorator to indicate that this is meant to act like a computed value not like a function. We also have an abstract method refuel which we indicate with the @abstractmethod decorator. This is our base class. If we are going to use it, we just derive from it. class ElectricCar(Car). Now we are deriving from it. Here we create a specialized, initialized initializer __init__ that takes only two values, model name and price and then it calls the superclasses one and always passes electric and zero so you don't have to worry about that when you use the ElectricCar. It overrides drive, and it overrides and must override, refuel. On both of those, there is no key words around it. You just do it, and it happens. It's easy to forget, but you really need to call super.__init__, there is no implicit constructor chaining. Like, if I just create a constructor it's not going to automatically call the default constructor the bass class, and it's bass class's default constructor. And so on. So make sure you always remember to call the bass class init in your initializer. You saw that Pycharm helped out with that as well. Overridden methods, you need no modifiers. There's not like override and virtual or anything like that. But, as we saw, you must implement the abstract ones or you cannot create an instance of this class. It in itself will be effectively abstract as well.
|
|
|
transcript
|
3:53 |
Here we in our program application. Let's break this up a little bit. So this part is for creating cars and driving them. We also want to park the cars when we're done. I want to do that a little bit separately. So let's go over here and create a method. It's called drive_cars, or let's call it use_cars. Then we're going to have another one over here called park_cars. And we'll pass cars in like so; and we'll just go ahead and write it here, I guess. And let's be really clear, so it helps us out a lot. We're going to take a list of cars. Then we'll make sure everything's hanging together. Yes, it looks like it is. So, the idea is we're going to create another class that has some other special behaviors called ParkingLot. It's not going to participate in the object hierarchy of what we had before but it's going to do a couple of interesting things. First of all, when I create a ParkingLot it's going to have different levels. Think of a parking garage; there's level A, level B, level C. Sometimes they get created like the orange level and the green level or, you know the carrot level, whatever. We're going to go basic; we're going to have level A, B, and C; and we're going to have a spot 1, 2, 3, 4, whatever in those. We're going to take a constructor. We're going to create a __init__, and it's going to take a string, a list of strings called spot names. And be a list of str, like so. And we can use PyCharm's magic to just add this as a field but we don't actually want to. Because there's just not enough information for us to store. We need to know what are the spot names and is some car parked in there. And if it is, what car is actually parked in it? So what I'm going to do is create a dictionary called spots, and we can say this is a dictionary like this. You technically can also write it like this but let's be explicit for a second. for n in spot_names. We're going to to set, create an entry in the dictionary and we're going to currently set it to be None. Okay, this is what we need, we, when later on we're going to put a car into into that spot. So we'll be able to say the free spots are the ones where it's None; and the ones where it's not None that is, we could pull the cars out and work with them. And this is totally fine. We could, we could roll with this but I want to show you something else we can do in Python that's cool. We talked about the list comprehension, remember? 2 n, something like this. And it even had an if statement here. This is a little bit like LINQ. This generates a list. We can actually generate a dictionary in a similar way. So we can say self.spots and we could put a type here if we wanted. We could say this is a dict of str, Car. Like that, I think this is what we need to say. We can say this is equal to not square braces but curly braces and put a little expression here. So then it, the way it goes you say, key:value. So let's say n:None and then for n in spot_names, like this, all right. So what that's going to do it's going to create a, the same thing here. So, like, we create the dictionary, then we loop over and we put an entry for the name and we're putting None in there. And we have self.spot_names, spots of whatever. Notice Car, Car, Car, Car, Car, Car. Because we told it, it's not just a arbitrary dictionary but key is a string and the value is a Car. Technically, this should be an optional of car. We're going to be as accurate as possible but really we'd be able to get away with it, right. Obviously this is, something we want to indicate. So here is our parking lot, and we're going to be able to store cars into it.
|
|
|
transcript
|
4:59 |
Well, the parking lot is interesting and we could come up with a bunch of names like, A1, A2, A3 B1, B2, B3 but let's have the parking lot create a pre-initialized version of itself giving more primitive data like if I have five levels and six spots per level or something like that, so we're going to create a static function and just like with the abstract function we're going to do that with a decorator, so we say @staticmethod def I have created some spots per level which is an integer and the number of levels which is also an integer. This is going to return a parking lot notice it's not going to work because the way Python operates as it creates this class is it doesn't really exist as a name until after line 19 so as we saw before we put quotes here it's kind of annoying but that's how it is. What we need to do is create a list that probably looks like an array to you but that is not an array that is a list that you can dynamically grow just like lists of string or list of integers and have some level names in our world we won't be able to go above, I don't know like six or seven levels but that's all right. We would have levels A, B, C, D, E and F here and then we're just going to do a double loop. hold off on this part we're going to adjust it in one second here. Put a pin into this, a level and then adjust the number, so like, A1, A2, A3. Obviously we want to only as many levels as there are so if they pass in two, we want to get two if they pass in four, we want to get four. Let me introduce you to a unique and super powerful idea here in Python so we don't really have a whole dedicated section on this but let's just say we have these level names here like this. There's this concept in Python called slicing so we have level names, just say L=level name so I can write less, we can say L is 0 and that gives us the first one, how if 1 give us the second but in Python you can put a range in here. I could say 1 to 3 and that will give me the one index and then this is a non inclusive upper bound. So 1, 2 and then that's it, so if I did 1 to 4 that would be B, C, D and I put it in the right spot. Like that, B, C, D. So what we can do is we can actually use this idea, slicing, to get the amount that we need there assuming that it doesn't exceed the length of our list, which is 6. What we can do is we can say L, our level names and if you want to start at 0 you can just say colon, you're also saying 0: it's implicit, and then we want to go in the first, if we want to get 4 entries we could put 4 here, we get A, B, C, D and so on. With that in mind, what we can put right here is we can say colon levels and as long as it doesn't exceed 6 we're going to get what we want. If it does exceed 6 it doesn't crash it just stops giving us more items. So either we want to get that back or we'll get some subset of that. All right so this should create the level names and then we can create a new parking lot and what this one is just the names not the data specified, so we're just going to pass the names, like that. Let's go and try to use this. So where we do our park let's say lot = parking_lot like that. And we actually want to call the factory method. Let's say we want to have 4 spots per level actually let's go with 5 spots per level and then we want 3 levels. So it should be A1 through A5, B1 through B5 C1 through C5 and then just to make sure this works we'll deal with more interesting stuff in a second. We can just print out the spots. So here we go, notice it's all wrapping along but we have A1, A2, A3, A4, B1, B2 it looks like we're off by one and that is because we want to go there. Plus one, here we go. A1 through A5 and right now there's no cars parked in them. Make sense? We were able to use our static method to create our staticmethod decorator to create a static method and then we used that to do the little extra leg work to pass over just the names based on the data they gave us, we'll do that here and then the constructor actually uses a dictionary comprehension to convert that to the data structure it needs to do its job.
|
|
|
transcript
|
2:47 |
Now that we have our parking lot and over here, we were able to create it. Let's go and actually park our cars. We've got to get them out and drive them around have lots of fun and we fuel them back up. It's time to park 'em. I'm going to say for c in cars lot.park, and we'll just pass the car over. Now lot's just lot, like this, easy enough. Notice there's a little marker here from high term saying it doesn't exist, but we can add a method and it will automatically write it. Notice it does itself, say car, say car like that. So now what are we going to do? How do we get this to park the car? Well, the job that really we have to do is find an empty spot and then put the car in it. So what we have to is we have to say for i in self.spots. Now if we just loop over this this will just give us the keys back and that's okay but I'd like to also have the value as part of the loop without an extra step. So I can say dot items, then if I just print let's say print I like that, if we run that this is actually a tuple. What it is, is a key and the value. So I'm going to say k, v and do tuple unpacking. And do that, and then we won't really need this, you'll see. So if we run it, you can see the version of the keys and then that would either be car or right now it's none. So then it becomes super easy. We just say if not v, or you could say v is None this may be a better way to say it if that's true then we want to put a car into that spot. Then we just say self dot spot of that key as that car. Break, can go over here. And let's just do a quick print of the lot.spots. And we can actually use this thing called pp for pretty print to look at this a little bit better, like this. It prints out dictionaries kind of like nice JSON-style. Over here, here's our dictionary structure. A1 to A4, the first level is all booked out. I guess A5 is left, but here's our sports car basic car, electric car, electric car. These are parking in a very orderly fashion. Let's do like one more, let's do two more cars just so we can, let's see what we got. We can have a Leaf, I want this at 30. And over here let's do a Camaro, probably let's put 40. Just going to take a guess. So now we run it one more time. We can see we're making our way up to the second level. We're parking our electric cars up there. That's, I guess that would be our Leaf, wouldn't it? Okay, so we're able to park our cars, that's really cool. And we'll go ahead and comment this out 'cause we're not going to really want that. But here's how we can create this function this factory method and then use the thing that got created here.
|
|
|
transcript
|
4:25 |
There were two reasons I added this idea of the parking lot. The first one was I wanted to talk about the staticmethods and how we can do this to create a factory type of thing. Here's the second. So, what I want to do is instead of just printing this out and go Oh, this is a super way to look at it. I'm sure my users would love to just have a flat dictionary dumped here with no data in it. There's a couple of improvements. First of all notice this is not an incredible representation of the SportsCar or the BasicCar. Whatever, right? It would be nice to have something better. So, I can go to the car and I can implement one of the what are called, magic methods or Python data model methods. And those are the dunder methods. So, if I go over here and type def and double underscore I have abs for absolute value, add async Enter what ending what something means what boolean conversion, deep copy copy Notice there are a ton of these things here. In .NET, you might override what ToString mean here. So we can do the same, like this. But it actually turns out there's two that get called in different situations. You can, if you use it in a string this get called if you just dump it out like we just did than this one gets called. We can actually just return one when the other exists. So let's just return a string that has the type name here. And then, maybe it says like the model name and the price. And if want to have digit grouping not too many zeros, things like that say put a little format, :x.0f,0f I think it is :,0f There is a comma, There is a .0f and over here, we are going to say type(self).__name__. I think that'll do it. Let's run it again. Check this out. Sports car. Model. Corvette. That's the price. Basic Car. Wind Star. Price, notice the digit grouping and there is no extra zeros even though it's a float. Pretty cool right? So this these two methods represent part of Python's special data model their dunder methods. This is how you implement some of the core interfaces of Python. So for example, what I would like to do up here instead would say something like this for spot, car in lot: something like that. I'd like to print out a statement about it. Like this. And I would also say if car, like so we got to make sure there is a car here and then we are going to print it out. We don't want to print the empty ones. I noticed, PyCharm says mmm We thought there would be a collections.interval here but this is just a random parking lot. It's not going to go so well if you try this. Let's see. Nope. It didn't go so well. Nope, not interval. This should be like C# compilation error object lot is not IEnumerable<T> or something like this right? So, how do we fix this? Well, we go back and we use one of these dunder methods. These magic methods. Like the constructor is. So we go over here. I'll put it below. And here is called __iter__. We implement __iter__. And what we have to do is return something that is the collections we are trying to loop over. Let's just say i, yield i. Here we go Created a generator that shoots out the items. So here we go. Here is the spot. It is A1 and it has the car, sports car which has this represents this, this two string equivalent, the __str__, implementation over here. Pretty cool huh? This lets us dig into the classes and change the way they basically intergrate the Python language. Right? We implemented __iter__ over here to allow us to loop over the lot. And then we implemented __repr__ and __str__. This one would be the str. But if we printed, we just did print car like that would be the __repr__ version we implemented that here to change basically the two string representation for that object.
|
|
|
transcript
|
1:28 |
While Python itself doesn't have separate interfaces outside of the concept of just maybe an abstract base class you did see that there are certain types of functions we can optionally implement that have the same basic effect. For example, our parking lot we wanted to be able to use it in a for in loop. How do we do that? Well, we have to add the __iter__ method here. And that was super easy. We just created a little generator. We said for item in self.spot.items yield item, right? No big deal for us to do that yet this is how we were able to use the lot within a for in loop to get those items back out. This method here, this __iter__ this is Python's equivalent of what would happen in C# if you implement IEnumerable<T>. There are tons of these special methods. There's actually a guide over here by Rafe Kettler who did a really nice job of combing through each one explaining what it does what it's about when you use it, and so on. This is a huge long article. I don't want to go through all of them. I just touched on a few of the key ones __str__, __init__, __iter__, __repr__, alright. There's a bunch more that you'll want to know about or at least know that they exist and then you go learn about 'em like, Oh, I actually probably could implement this and, you know, make it do whatever it is you're trying to do. Our parking lot now effectively, in like C# terminology implements IEnumerable by using this magic method which they're sometimes called, or dunder method.
|
|
|
|
25:26 |
|
|
transcript
|
1:26 |
Package management and programming languages is so important. It used to be kind of a rare thing and it made working with other libraries super painful. In C# you have the base class library, and all the stuff that's shipped with it, like EntityFramework.dll and so on and that was great because it was right there. But if you wanted something else, how did you get it? You went out to GitHub or, after a bit, SourceForge and you download a library and you copy it into your project and you start working with it. Well, that's probably okay it's not super validated or anything like that it maybe came from somewhere sketchy but let's assume, you know, let's just put the security stuff at the side for a minute. Just from... Even if the code is trustworthy there are problems here, right? How do you know when there's a new version? How do you know if there's some kind of issue that needs to be fixed? How do you help someone else get the same version? If they go and download something from that same place maybe it's a different version and it behaves differently. So package management is some infrastructure that will list all the available libraries that are registered with it for your environment: C#, Python, whatever. Now, you see, I'm going to use these libraries and make sure you get the right version you can always get the same version. In .NET you've had NuGet for quite a while and that's been really important there. So much so that Microsoft even ships some of .NET itself through NuGet. You'll be happy to hear that Python has something equally awesome, maybe even more so.
|
|
|
transcript
|
3:03 |
As I hinted at before NuGet changed the way you work in .NET. All of a sudden, there are many, many libraries and I mean many. When I took this screenshot to put this presentation together a few days ago there was 174,000 unique packages or libraries available and you can just go to Visual Studio check a few boxes, and boom, you've got them added to your app and you always get the right version and it made such a huge difference for working in .NET. If you're going to come over to Python you're going to want to make sure there's something like this. 172,000 packages, that is killer. To be fair, a ton of those-- not a ton a lot of those are Microsoft library packages like I hinted at in EntityFramework and EntityFramework Core and that kind of stuff cause a lot of .NET itself is even delivered through this mechanism but there's many, many, many of those that are third-party libraries you can bring in like json.net or something like that and work with it within your application just almost as easy as right-click, add reference. Just right-click, manage NuGet packages. So if you're going to come to Python it would be really nice if Python had something kind of like this, right? Some way to say I want to use these libraries make sure they're part of my project keep them in sync. If there's an update, tell me that there is and give me a mechanism to get the latest. Well, luckily, Python has something completely awesome PyPI, Python Package Index. And PyPI has a bunch of libraries. You saw how cool NuGet was? Check this out, 199,000 packages. Actually, since I took this screenshot but before I pressed record it's surpassed 200,000 packages. There are so many libraries in Python. I think this is one of the most exciting parts of this course because so far we've been working with the language. .NET's great, but where the true magic is where the special stuff happens is when you start to build out of these other libraries. All of a sudden we can talk to databases and call web APIs and build websites and applications and all these types of things and this all comes from these external libraries we can bring into our applications. So NuGet is awesome. PyPI, I think, is even a little bit more awesome. It has more packages. Python itself is not delivered this way so this number is maybe a slightly bigger gap as I hinted. Final word on the pronunciation. Some folks say pie-pie. Alright? Py and then the PI is like the math pi so you say pie, people say pie-pie. It's not pie-pie. It's pie-P-I, Python Package Index. How can I say that with confidence and not go, well, maybe I just say it differently? Maybe I just have a different opinion. Hmm, the Talk Python To Me podcast I've interviewed Guido van Rossum the creator of Python. I've interviewed several times the people who have created and continue to run this website here. And I ask those people who run the website and Guido just use the words ask them, how do you say this the letters P-Y-P-I, in your world, how do you pronounce it? Pie-P-I, just so you know when you're talking to other folks.
|
|
|
transcript
|
2:25 |
Knowing the language, Python or C# either one of 'em, it's important. But it's actually a pretty small step to being effective in that technology. Knowing the base class library or what's referred to as the Standard Library in Python, quite important, right? There's so much more to know about the libraries that come with these two languages than there is just the language itself. As we just saw, there's 200,000 libraries that I can go build stuff with. How do I have any hope of figuring out that which ones I need to be using as a new person? One of the big challenges coming to a programming environment is I need to do something. I got to figure out, do I have to build that from scratch or is there some built-in library or is there some third-party library that I can go grab? So let me introduce you to Awesome Python. This is just a website, also has a it's backed by a GitHub repository and the idea is people submit cool libraries and packages for Python under different categories. And this is not just an exhaustive list. In order for it to make it on this list, it has to get a certain number of votes and things like that. So let's imagine that we want to build something and we want to talk to a database. So databases are actually the databases so we'll look at the drivers. So I could talk to MySQL using these things or Postgres. Or if I want to talk to, you might care about Microsoft SQL Server, you could use PyMySQL or here's PyMongo for talking to MongoDB. But, you know, obviously you could just directly talk to them, but you'd probably be better off using an ORM, so we've got a ton of awesome ORMS and little descriptions about why they're interesting. The one that we use for Talk Python Training is actually MongoEngine, which is an ORM or ODM on top of PyMongo, which talks to MongoDB. Absolute joy to work with, not really relevant for this course, but you know, it's listed right here as one of the four ways to do it. You want to talk to DynamoDB or Redis or something like this, right? So you just pick something. You want to figure out how you do computer vision? Go over here and, Oh look, OpenCV. OpenCV is a great library for working with computer vision and Python. But I recommend you start here with Awesome Python if you need to work on some project or you got to get a functionality for some category and you're like, Oh, I wonder what's here? These are here, not just because they're in existence but they're here because they actually got voted as one of the better libraries for that category.
|
|
|
transcript
|
2:54 |
Well things are about to get really fun and exciting, we're going to write a program that uses a bunch of cool libraries and first we're going to check out the equivalent in C#. So over here I've created this thing called Ch5_nuget and it's an application that does web scraping. You can see it proclaims it with its title right there. The idea is that we're going to go visit Talk Python my podcast here, and there's a little shortcut URL if you just go, like, 212 or just, you know that slash a number, it will automatically find its way over to the actual thing that it's looking for. So what we're going to do is we're going to write a program that's going to go and go right now it's going to go for the ten episodes 220 to 230, and its going to go actually download all of the HTML and it's going to get that HTML and it's going to parse it and try to pull out the title that's in the H1 tag and then it's going to say that it found it. Let's just first run it and see what it does. Alright so it's running, look, it's getting it. Found the title, 'Machine Learning in the Cloud.' Empowering developers with this, and so on, right. 'Twelve Lessons from a Hundred Days of Web.' And off it goes. And, now it's done. It went and downloaded all that stuff off the website it parsed the HTML, and so on. Now, this whole program is 76 lines of code. Do you think we're able to do that in 76 lines? No, that's super complicated stuff but the cool thing is, we didn't have to worry about it. This is something that we're able to just reference off of NuGet. So let's go look at the packages that we're working with here. Manage NuGet packages. Go to installed, and the one that we have installed here is HTMLAgilityPack and because we're doing .NET Core it's the .NET Core version of that. So the idea is, we're going to go over here and we're going to download this, and then this and then this get HTML, I don't know, get title from HTML it's just this. Maybe you caught it before. And we go go in and we create an HTML document we load up the stuff we got from the website and we just select the single node, H1 and get the innertext and trim it. And as you saw, it works like a champ. Alright, those are the titles of those episodes, like those are the H1 tags if you went in and found it. We're also happen to be using HDP client so we use some from there, but also we've got .NET Core itself coming down that way as well from NuGet I believe so we were able to go out and find this library and add it, and we could even do things like see if there's any updates. I don't know, are there? It doesn't look like it. But if there were, it would tell us, right? So if there were updates for these packages we could push a button and it would change it and get new ones. This is a pretty cool little program that goes and does that, downloads it, pulls up the title and just prints it out. It's actually doing a ton of work for how little code we had to write.
|
|
|
transcript
|
7:58 |
As we saw, Python has PyPI with over 200,000 packages. You would think we should be able to recreate that application you saw over in C# that screen-scraping one that just downloads the header the h1 and then shows it to us. Turns out, of course we can. We're going to use three cool libraries to do it. So let's talk about a couple of things here. First of all, in order to declare it these are the requirements that my program depends upon we typically have a requirements.txt or there's a couple of other formats that are becoming popular but requirements.txt is probably still the most popular. And the idea is you just list the names of the packages like if I wanted to use HTMLAgilityPack like as you saw, I would just write that boom, it's ready. Notice that PyCharm's are like we got to install it you want me to do that? It actually doesn't exist for Python I don't think. We need something called Beautiful Soup instead. But you just list the names of them here. Sometimes you would put the version like 0.1.0. like that actually double equals and then it says oh you have the wrong version of Colorama and you want me go get that? Not right now. So you can put them there. A lot of times what people do is, they'll just play around and just install them manually and then go back and recreate this requirements.txt, once they have decided on what they actually need for their program. So let me show you how you would ad hoc install it not just play with this requirements.txt purely within PyCharm. So lets go over here. Now first thing to notice if I want to work with it, the tool we work with work is called pip. And I can thing do like pip list, but the problem is if I ask which pip, notice it wants itself to be updated but kind of irrelevant we don't care about it okay. Which, hold on, I kind of over wrote it. Which pip3. Here we go, got it to save finally. So it's out of my primary Python 3 right now 3.7 on the system. This is not the same one if I say pip list as you saw it there is tons of stuff here but the only thing we declared is Colorama what's going on? Or remember you have to always if you're using a virtual environment then you almost always should you need to make sure that you activate them. On windows that would be venv\Script\Activate. Not that, not here though. We have to say dot to apply to this shell and then venv/bin/activate so on Mac and Linux this is a command and notice we have this now. Okay, so now we can install stuff we can do a couple things like I said pip install colorama. We did this earlier so it's already good let's make this warning go away apparently a new version just released. So you can use pip to manage itself it's very meta, kind of satisfying that way. Seeing as we already have colorama there and we do a pip list we should have the two tools that manage packages and then Colorama apparently that is the version we actually had. And maybe we want some more, so if we're going to let's say we want to work with pip install bs4 for Beautiful Soup we hit that and notice it either downloads or used the cache version and it's actually pulling down a couple of things that it needs so it takes the transitive closure of all the dependencies of all the things you've asked for, right? So this is pretty cool, now we can do pip list and we should have those listed there but if we have one of these requirements. Let's say, let's put bs4 and let's put one more thing in here httpx. Would let me making a HTTP client request we could use requests, that's most popular but later we going to use a feature of this library that's not available on requests and I'm going to t |