[{"content":"If you\u0026rsquo;ve been around here before, you might have seen my post on setting up PyCharm for Maya Python development. It\u0026rsquo;s been one of my more practical posts, and for a long time it reflected how I actually worked. PyCharm was my IDE of choice for Maya scripting, and I didn\u0026rsquo;t have much reason to look elsewhere.\nI\u0026rsquo;d tried VS Code over the years and never really landed on it. Getting it properly configured for Maya — pointing it at the right interpreter, getting reasonable autocomplete — always felt like more friction than it was worth. PyCharm just worked, and once you had a good setup going, it was hard to argue with.\nRecently I went back to VS Code and gave it another proper shot. This time, it clicked. And in revisiting everything, I also realized my old workflow had a limitation I hadn\u0026rsquo;t fully reckoned with — something I\u0026rsquo;ll get into below. Workflows evolve. It is what it is. Here\u0026rsquo;s where I\u0026rsquo;ve landed.\nTwo things that made the difference uv The first is uv, the Python package and project manager from Astral. If you haven\u0026rsquo;t run into it yet, it\u0026rsquo;s worth a look — it\u0026rsquo;s fast, opinionated in the right ways, and has become my go-to for managing Python environments.\nFor Maya development specifically, the challenge has always been the same: getting a Python environment set up that gives you both good autocomplete in the editor and the ability to actually execute code against Maya in headless mode.\nIn my PyCharm post, the approach was to point PyCharm directly at mayapy as the system interpreter — no virtual environment involved. That works, and it unlocks a lot, but it means you\u0026rsquo;re working in Maya\u0026rsquo;s Python environment directly. Any packages you install go in there with everything else, and you lose the isolation and reproducibility that a virtual environment gives you.\nWith uv, the goal was to get to a venv-based workflow. The problem is that when you create a virtual environment and try to run code with mayapy in headless mode, Maya\u0026rsquo;s own site-packages folder isn\u0026rsquo;t on the Python path inside your venv — so anything that depends on Maya\u0026rsquo;s modules can\u0026rsquo;t be found.\nIn my old PyCharm setup, the fix was a manual step in the interpreter settings — you had to go in and explicitly add Maya\u0026rsquo;s site-packages directory to the path. It worked, but it was easy to forget, and it was something you had to redo whenever you set up a new project.\nWith uv, we solved this more cleanly. As part of the thin wrapper script that creates the virtual environment, we now automatically drop a .pth file into the venv\u0026rsquo;s own site-packages directory. That file contains a single line: the path to Maya\u0026rsquo;s site-packages. Python picks up .pth files automatically at startup, so the moment the venv is activated, Maya\u0026rsquo;s packages are on the path — no manual config step, nothing to forget, nothing to redo.\nThe wrapper script lets you define which Maya version to work with, which then gets passed to uv. For example:\nuv sync --python maya2025 Behind the scenes, this becomes:\nuv sync --python \u0026#34;C:\\Program Files\\Autodesk\\Maya2025\\bin\\mayapy.exe\u0026#34; You could pass the full interpreter path like this every time and use vanilla uv if you wanted — it works. But it\u0026rsquo;s a bit tedious, and you\u0026rsquo;d also miss out on the automatic .pth setup and the auto-sync of maya-stubs that the wrapper handles for you. The script just takes care of all of that in one step.\nThe script handles setting up the venv and dropping in that .pth file automatically.\nOn Windows, that .pth file line looks something like this (adjust for your Maya version):\nC:\\Program Files\\Autodesk\\Maya2025\\Python\\Lib\\site-packages Worth noting: this isn\u0026rsquo;t a VS Code-specific trick. If you\u0026rsquo;re still on PyCharm, the same approach should work for you too — it operates at the Python environment level, not the IDE level. But it did solve the friction I was hitting in VS Code, and it\u0026rsquo;s cleaner than the manual path configuration I\u0026rsquo;d been doing before.\nAI-assisted autocomplete The other thing is that Copilot — and AI-assisted autocomplete in general — has really closed the gap that used to make PyCharm feel superior on the completions side. VS Code\u0026rsquo;s native autocomplete for Maya was always a weak point. That\u0026rsquo;s less of a concern now when you\u0026rsquo;ve got something like Copilot doing a lot of the heavy lifting on suggestions.\nA couple of areas where VS Code is notably better Once I was set up, a couple of things stood out as better in VS Code than I was used to in PyCharm.\nThe GitLab Workflow extension is the main one. MR reviews, pipeline status, CI feedback — it all surfaces cleanly inside the editor. The PyCharm experience always felt like it was playing catch-up by comparison.\nCopilot integration is the second. I\u0026rsquo;ll caveat that it\u0026rsquo;s been a while since I\u0026rsquo;ve been in PyCharm, so it may have improved — but I\u0026rsquo;d find it hard to imagine it hitting the same level of integration that VS Code has, given that both Copilot and VS Code come from Microsoft. It shows. Commit message generation is built right in. Copilot can look at what\u0026rsquo;s happening in the terminal and help you work through errors there. It\u0026rsquo;s woven into the editor throughout rather than feeling like something bolted on.\nTo be fair, I haven\u0026rsquo;t explored the newer AI-centric IDEs that have been popping up recently. I\u0026rsquo;ve stayed between these two main players, so it\u0026rsquo;s entirely possible there\u0026rsquo;s something out there with even better AI integration. I\u0026rsquo;m happy with where I\u0026rsquo;ve landed though — there\u0026rsquo;s only so much you can realistically go and evaluate.\nWhat I do miss about PyCharm PyCharm is a more polished experience. It\u0026rsquo;s a commercial product built specifically for Python development, and that focus shows. Everything is there out of the box. You don\u0026rsquo;t have to go hunting for extensions, experiment with settings, or put in the upfront investment to get things feeling right.\nVS Code is the opposite. It\u0026rsquo;s general purpose, and making it your own takes real time and exploration. Finding the extensions that fit your workflow, getting them configured the way you want — none of that is handed to you. It\u0026rsquo;s a more DIY experience, and if you\u0026rsquo;re not in the mood for that, PyCharm\u0026rsquo;s polish is hard to argue with.\nOnce I\u0026rsquo;d put in the time though, I found I prefer where I landed. The trade-off of upfront investment for a better-integrated toolchain — especially around GitLab and Copilot — is one I\u0026rsquo;d make again.\nSo should you switch? If you\u0026rsquo;re on PyCharm for Maya development and things are working for you, there\u0026rsquo;s no urgent reason to change. The old PyCharm setup post still holds up for what it is.\nBut if GitLab and Copilot are a meaningful part of your workflow, VS Code has better answers for both now. And the setup story — which used to be the main argument against it — isn\u0026rsquo;t really an argument anymore.\n","permalink":"https://matfacer.com/posts/switching-from-pycharm-to-vscode-with-uv/","summary":"\u003cp\u003eIf you\u0026rsquo;ve been around here before, you might have seen my post on \u003ca href=\"/posts/the-best-pycharm-mayapy-interpreter-setup/\"\u003esetting up PyCharm for Maya Python development\u003c/a\u003e. It\u0026rsquo;s been one of my more practical posts, and for a long time it reflected how I actually worked. PyCharm was my IDE of choice for Maya scripting, and I didn\u0026rsquo;t have much reason to look elsewhere.\u003c/p\u003e\n\u003cp\u003eI\u0026rsquo;d tried VS Code over the years and never really landed on it. Getting it properly configured for Maya — pointing it at the right interpreter, getting reasonable autocomplete — always felt like more friction than it was worth. PyCharm just worked, and once you had a good setup going, it was hard to argue with.\u003c/p\u003e","title":"Switching from PyCharm to VS Code — and Fixing Python Environments with uv"},{"content":"A few months ago, I overcame a challenging hurdle in my spare time passion project. It seemed like I reached a dead end, but I got past it thanks to discovering a new Python package, SymPy.\nThe Background After going down the rabbit hole with reinforcement learning, I conceded my problem was best solved using a regression algorithm. Still, the best results I saw came from exploiting the training loop in the early days.\nI was hoping to have a trained model for an easier deployment to iOS, but alas. With the change in direction, I couldn\u0026rsquo;t take advantage of popular ML packages. While we can deploy their trained models, they do not offer on-device training. Also, Apple’s ML offerings didn’t pinpoint what I needed. I had to make things work at a lower level.\nFirst Attempt My research so far gave me a clearer understanding under the hood of a training loop. I already figured out my forward propagation, but the big missing piece of the puzzle was in the back propagation: finding the derivative.\nThe automatic derivative calculation is one of the biggest boons for using an ML framework. There is a lot of heavy lifting happening here with complex calculations. I consider myself to be a smart guy, and while I feel I am good at math, I am not some math wizard. My strength is problem solving and critical thinking. This math was looking too advanced.\nI started searching for new ways to continue moving ahead and found an article talking about how Swift was an auto-differentiable language. I didn’t realize that! Maybe it will solve all my problems! I wish.\nTo take advantage of the auto-diff feature, I had to install a preview toolchain of Swift. For lack of other ideas, I did. I set up my forward prop function to return the derivative, and it regressed to the solution I wanted to see for every problem I threw at it. I was thrilled!\nBefore moving on to the next set of tasks, I wanted to do my due diligence. When would the proposed auto-differential addition to Swift be released? After all, I wouldn’t be able to ship an app using an unreleased toolchain. It turns out there was no ETA. I couldn’t depend on this solution at all.\nOnward and upward! The exercise was still valuable because I confirmed this was possible. I just needed to figure out the derivative formula.\nEnter SymPy I started researching derivative calculations again and learned quickly it was not something I’d be figuring out on my own.\nMy efforts rerouted to revisiting the ML frameworks to see if they could expose the derivative formula they use for a network. No such luck.\nSoon I discovered SymPy, with “Sym” standing for Symbolic Mathematics. The library allows you to define a mathematic formula using variables without having to populate said variables. You can then run calculations on the formula, such as simplifying it or… calculating the derivative!\nBingo. SymPy was my golden ticket.\nNow, I still had some obstacles in my way. I was using a for-loop in my algorithm, as well as absolute value. How would I go about these?\nThe for-loop was just a summation. The Sum Rule shows to get the derivative of f + g, you add the derivative of f and the derivative of g.\nDerivative Rules - Math Is Fun\nSo, as long as I can calculate the derivative of the contents of my for-loop, I can just sum them after. See, “you can ignore the for-loop”.\nAs for the absolute value - it was trickier to figure out. Absolute value is weird for derivatives. It turns out, you can’t calculate it because it is not a continuous curve. The absolute value of 0 is 0 and therefore there is a single point where there is no tangent.\nThe trick for circumventing this problem is to take advantage of getting the square root of a squared value. Both functions have calculable derivatives, and of course, it is equivalent to getting the absolute value.\nDerivative Rules - Math Is Fun\nI started down this road, but it turns out there is an even easier way. SymPy has a keyword argument when defining your symbols to show your symbols will all be real numbers: real. Toggling this to true fixed all my problems with absolute value.\nIn Closing After this, I had my derivative formula. Plugging it into my Swift code, I had my complex regression working on-device. SymPy was a godsend and I wouldn’t have solved these problems without it.\nThe only oddity I experienced was after getting it to solve the derivative. The equation was still long, and calling the simplify method made it even longer. I simplified it down to something concise and readable, so I don’t know why it struggled.\nThe documentation is top-notch and has interactive code snippet examples throughout that you can run in-browser. Don\u0026rsquo;t be afraid to have a look because they make it easy for you.\nSymPy is fantastic and should always be in your back pocket as a secret weapon if you’re ever in a mathematical bind.\n","permalink":"https://matfacer.com/posts/sympy-to-solve-a-low-level-ml-training-loop/","summary":"\u003cp\u003eA few months ago, I overcame a challenging hurdle in my spare time passion project. It seemed like I reached a dead end, but I got past it thanks to discovering a new Python package, SymPy.\u003c/p\u003e\n\u003ch2 id=\"the-background\"\u003eThe Background\u003c/h2\u003e\n\u003cp\u003eAfter going down the rabbit hole with reinforcement learning, I conceded my problem was best solved using a regression algorithm. Still, the best results I saw came from exploiting the training loop in the early days.\u003c/p\u003e","title":"SymPy to Solve a Low Level ML Training Loop"},{"content":"There\u0026rsquo;s no denying - Maya makes development hard.\nPython is one of the most popular programming languages in the world as of 2022. The language supports many great workflows, but most are off-limits when working with Maya. Even just setting up an IDE with MayaPy has been a challenge through the years.\nToday I will share how I set up PyCharm to work with MayaPy and how it enables a super-slick workflow for unit testing.\nGetting Maya Python stub files To get started, we\u0026rsquo;ll fetch Maya\u0026rsquo;s devkit. If you\u0026rsquo;re unfamiliar, the devkit contains autocomplete stubs for Maya\u0026rsquo;s Python modules. Download the appropriate one for your version of Maya from here.\nWith it downloaded, you\u0026rsquo;ll find the stub files at the following location inside: devkit/other/Python(x)/pymel/completion\nThere is a special kind of stub file PyCharm supports that we will take advantage of - pyi files! I reached out to Autodesk several years ago when I first learned of pyi files and asked them to begin including them with Maya distributions. So, if you see a folder named \u0026ldquo;pyi\u0026rdquo; in the devkit location from above, use it. If you are on a version of Maya where the devkit doesn\u0026rsquo;t include pyi files, we can make them ourselves! All you need to do is rename the extension of the .py Maya stubs to .pyi. Here is a short script to help you with the renaming.\nimport os import shutil def rename_from_py_to_pyi(py_dir, output_dir): shutil.copytree(py_dir, output_dir) for root, _, files in os.walk(output_dir): py_files = [os.path.join(root, f) for f in files if f.endswith(\u0026#39;.py\u0026#39;)] for f in py_files: os.rename(f, \u0026#39;{}i\u0026#39;.format(f)) if __name__ == \u0026#39;__main__\u0026#39;: # Update below with the appropriate local paths for your machine rename_from_py_to_pyi(r\u0026#39;/Users/mat/py\u0026#39;, r\u0026#39;/Users/mat/pyi\u0026#39;) Find a nice home for these pyi stubs on your hard drive, as we will be using them when we set up our MayaPy interpreter. The most obvious place to put them is in the, otherwise empty, devkit folder in your Maya installation location.\nSetting up the MayaPy interpreter Now that you have a stubs folder full of .pyi files, it is time we set up our MayaPy interpreter in PyCharm. If you\u0026rsquo;ve done this before using past approaches, this time will be slightly different because of pyi, so be sure to follow along.\nIn PyCharm\u0026rsquo;s Settings, go into \u0026ldquo;Project: \u0026rdquo; and choose \u0026ldquo;Python Interpreter\u0026rdquo; from the left-side menu. Click on the \u0026quot;\u0026hellip;\u0026quot; button to the right of the \u0026ldquo;Python Interpreter:\u0026rdquo; dropdown and choose \u0026ldquo;Add\u0026hellip;\u0026rdquo; Select \u0026ldquo;System Interpreter\u0026rdquo;. Press the \u0026quot;\u0026hellip;\u0026quot; button to the right of the \u0026ldquo;Interpreter:\u0026rdquo; dropdown. It will pop up a new window. Navigate to your Maya installation\u0026rsquo;s bin folder and choose \u0026ldquo;mayapy.exe\u0026rdquo; (or \u0026ldquo;mayapy2.exe\u0026rdquo;). Press OK Press the \u0026quot;\u0026hellip;\u0026quot; button to the right of the \u0026ldquo;Python Interpreter:\u0026rdquo; dropdown again. This time choose \u0026ldquo;Show All\u0026hellip;\u0026rdquo; From the list of interpreters that appears, choose the one you just made. Press the pencil, \u0026ldquo;Edit\u0026rdquo;, button to give it a better name. Rename it to something more descriptive. I like to follow the template of \u0026ldquo;ExeName AppVersion PythonVersion\u0026rdquo;, i.e. \u0026ldquo;MayaPy 2022 3.7\u0026rdquo; Press OK to accept your changes. Select your newly renamed Python Interpreter again from the previous window. This time, press the tree, \u0026ldquo;Show paths for the selected interpreter\u0026rdquo;, button. Press the \u0026quot;+\u0026quot; button to add a new path. Navigate to the \u0026ldquo;pyi\u0026rdquo; stubs folder that we made previously, wherever you decided to keep it. Press \u0026ldquo;OK\u0026rdquo; on all windows until your settings updates have been accepted. You\u0026rsquo;re all done! Congrats!\nThere were a lot of steps here, but this is extremely straightforward after you\u0026rsquo;ve done it once.\nWhy is this awesome? Direct Set-Up This first reason is admittedly minor, but it is more direct than popular recommendations in the past. Previously it was suggested to do all of the steps above, but then also remove Maya\u0026rsquo;s site-packages folder from the interpreter paths to set up auto-complete properly. This removal step was always unintuitive but necessary so as to avoid conflicts between the stub files and the same modules found in Maya\u0026rsquo;s site-packages folder.\nWhy don\u0026rsquo;t we need to solve the conflict problem here? More on that in a bit.\nAll-encompassing Auto-complete Because we do not remove Maya\u0026rsquo;s site-packages folder, if there are other packages or modules installed there you will get auto-complete for them also since they are all still on the pythonpath.\nThe Power of pyi Coming back to the question, “why don’t we need to solve the conflict problem here?” The answer to that question comes from those pyi stubs we made.\nThe pyi files unlock special functionality with PyCharm. PyCharm knows to use these files in the editor for auto-complete purposes but then ignore them when running code and use the real modules instead. This is game-changing for MayaPy developers, and this is what makes this setup so great.\nWhy, you ask? Well, this magic brings our environment more in line with a regular Python development environment. You still can’t create virtual environments (at least I haven’t got that working yet), but we do unlock several other great workflows - and with minimal effort!\nUnit testing You can now take advantage of unit testing directly inside PyCharm! This works using the default built-in unittest module and with PyCharm’s test running interface.\nThe only thing you need to do to get this working? Initialize Maya! In your tests folder, create an __init__.py file and put your code there for initializing Maya’s standalone mode. Run your tests, and that __init__.py file will be run, and the rest just works.\nCoverage If you don’t already know, pip works with Maya and has for years. You can pip install the coverage package and run your unit tests with coverage now, too! PyCharm will give you line-by-line highlighting to show you what is covered and what is not.\n__name__ == “__main__” Similarly, slap that same maya.standalone.initialize() code in a __name__ == “__main__” block at the bottom of a file, followed by some test code for testing your module, and be able to run it. Super fast iteration without even having to launch Maya!\nPySide iteration Speaking of which, if you’re clever about structuring your PySide GUI classes, you can do most (if not all) of your GUI work by launching it from PyCharm now!\nCreate the main class to contain the bulk of your GUI, but omit code that handles integrating it with Maya’s GUI. Save that to be implemented in a Maya-specific subclass. Call the main class from within PyCharm, within your __name__ == “__main__” block, and then call the Maya-specific class inside Maya. Say goodbye to all that unproductive time waiting for Maya to start up and shut down!\nIn closing I’ve been using this PyCharm setup for several years, and I’ve been thrilled with it. It feels like a massive step toward normal Python development for Maya. Unit testing and improved iteration truly transform the experience. I hope others will be excited to discover how easy it is to unlock these features, and if you discover any other cool workflow improvements I\u0026rsquo;d love to hear about them!\n","permalink":"https://matfacer.com/posts/the-best-pycharm-mayapy-interpreter-setup/","summary":"\u003cp\u003eThere\u0026rsquo;s no denying - Maya makes development hard.\u003c/p\u003e\n\u003cp\u003ePython is one of the most popular programming languages in the world as of 2022. The language supports many great workflows, but most are off-limits when working with Maya. Even just setting up an IDE with MayaPy has been a challenge through the years.\u003c/p\u003e\n\u003cp\u003eToday I will share how I set up PyCharm to work with MayaPy and how it enables a super-slick workflow for unit testing.\u003c/p\u003e","title":"The Best PyCharm MayaPy Interpreter Setup"},{"content":"The project I am currently working on has an input form that takes doubles for some of its fields. I am using CoreData to persist my data and was surprised to find optional scalars are not supported.\nRegardless of whether or not Optional is checked, the type in the Swift codegen will always be Double and never be optional. This behaviour is not a bug, but rather just a difference in how Optionals work in CoreData - it refers to optional at save time.\nThis lack of optional data type creates a problem when trying to have a field for a Double type in an input form like I was attempting to do. No matter what, there is a value present - 0.0. I want the option for the TextField to be blank, and reserving the 0 value for a nil equivalent is not an option in all cases.\nI played around with NSValueTransformer for quite a bit, which at first appeared like the perfect tool for the job. Alas, I couldn\u0026rsquo;t get it working as I hoped. If I remember correctly, the dead-end was when realizing the transforming type needs to inherit from NSObject, which Double does not.\nThe Solution I finally landed on something that feels clean and doesn\u0026rsquo;t have much boilerplate, so I thought I would share.\nThe first step is to disable \u0026ldquo;Use Scalar Type\u0026rdquo; on your attribute in the Data Inspector.\nDoing this will change the data type in the Swift codegen from Double to NSNumber?, which you can see is optional (yay!)\nNow that we have an NSNumber? as our type, we want to extend our NSManagedObject codegen with a get/set as a Double?.\nextension MyEntity { var length: Double? { get { if let value = length_?.doubleValue, value \u0026gt; 0 { return length_ } else { return nil } } set { if let newValue = newValue { length_ = NSNumber(value: newValue) } else { length_ = nil } } } To call it out and make it obvious, please note that the attribute\u0026rsquo;s name in CoreData is length_, with an underscore at the end, and the calculated property we are creating in our Swift extension is length, without an underscore.\nThis code should be pretty straightforward stuff. However, it isn\u0026rsquo;t terrific to rewrite this every time you want a Double? type. Instead, you can change this to the following to make it reusable with little repetitive code.\nextension NSManagedObject { func optionalGet(storedValue: NSNumber?) -\u0026gt; Double? { if let value = storedValue?.doubleValue, value \u0026gt; 0 { return value } else { return nil } } func optionalSet(newValue: Double?, destination: inout NSNumber?) { if let newValue = newValue { destination = NSNumber(value: newValue) } else { destination = nil } } } extension MyEntity { var length: Double? { get { optionalGet(storedValue: length_) } set { optionalSet(newvalue: newValue, destination: \u0026amp;length_) } } This code now extends NSManagedObject instead, adding general functions for getting and setting Double?. The extension for our CoreData entity calls those, passing our stored value to the setter as a reference.\nI also needed Decimal? as a stored type. Here is another extension, overloading the optionalGet and optionalSet to work with Decimal?.\nfunc optionalGet(storedValue: NSDecimalNumber?) -\u0026gt; Decimal? { if let value = storedValue?.decimalValue, value \u0026gt; 0 { return value } else { return nil } } func optionalSet(newValue: Decimal?, destination: inout NSDecimalNumber?) { if let newValue = newValue { destination = NSDecimalNumber(decimal: newValue) } else { destination = nil } } ","permalink":"https://matfacer.com/posts/coredata-swift-scalar-optionals/","summary":"\u003cp\u003eThe project I am currently working on has an input form that takes doubles for some of its fields. I am using CoreData to persist my data and was surprised to find optional scalars are not supported.\u003c/p\u003e\n\u003cp\u003eRegardless of whether or not Optional is checked, the type in the Swift codegen will always be Double and never be optional. This behaviour is not a bug, but rather just a difference in how Optionals work in CoreData - it refers to \u003cem\u003eoptional at save time\u003c/em\u003e.\u003c/p\u003e","title":"CoreData Swift Scalar Optionals"},{"content":"I\u0026rsquo;ve been spending a lot of time in SwiftUI lately and, so far, I love it.\nWhile it is remarkably flexible and powerful, it is still very young. There are still pain points from what seems to be a lack of coverage in the framework. Worse still, because it is changing and updating so rapidly, I am finding that much advice on StackOverflow and many blog posts are outdated already.\nOne such area is with entering currency values in an application. Searching this topic brought back many results, but all of which seemed overly complicated. I returned to this today and came up with what I feel is a solid and straightforward solution, so I thought I would share!\nimport SwiftUI struct SelectOnFocus: ViewModifier { func body(content: Content) -\u0026gt; some View { content .onReceive(NotificationCenter.default.publisher(for: UITextField.textDidBeginEditingNotification)) { obj in if let textField = obj.object as? UITextField { textField.selectedTextRange = textField.textRange(from: textField.beginningOfDocument, to: textField.endOfDocument) } } } } extension TextField { func selectOnFocus() -\u0026gt; some View { modifier(SelectOnFocus()) } } public struct CurrencyField: View { @Binding var value: Decimal? @FocusState private var isActive var locale = Locale.current var formatter: NumberFormatter { let formatter = NumberFormatter() formatter.locale = locale formatter.numberStyle = .currency return formatter } public var body: some View { TextField(formatter.string(from: 0) ?? \u0026#34;0\u0026#34;, value: $value, format: .currency(code: locale.currencyCode!)) .selectOnFocus() .multilineTextAlignment(.trailing) .focused($isActive) .keyboardType(formatter.maximumFractionDigits \u0026gt; 0 ? .decimalPad: .numberPad) .allowsHitTesting(false) .overlay( GeometryReader { geometry in Button { isActive = true } label: { Color.clear } .frame(width: geometry.size.width, height: geometry.size.height) } ) } } struct CurrencyField_Previews: PreviewProvider { static var previews: some View { VStack { Group { CurrencyField(value: .constant(23.40)) CurrencyField(value: .constant(0.0)) CurrencyField(value: .constant(3.0)) CurrencyField(value: .constant(nil)) CurrencyField(value: .constant(391), locale: Locale(identifier: \u0026#34;ja_jp\u0026#34;)) CurrencyField(value: .constant(127), locale: Locale(identifier: \u0026#34;ru_ru\u0026#34;)) CurrencyField(value: .constant(67), locale: Locale(identifier: \u0026#34;zh-cn\u0026#34;)) CurrencyField(value: .constant(345), locale: Locale(identifier: \u0026#34;sv-se\u0026#34;)) } } .previewLayout(.sizeThatFits) } } And here are the results from the PreviewProvider.\nThe behaviour is similar to a currency field you often see in apps.\nThe text field is overlayed with an invisible button, blocking direct interactivity to the field. Pressing the button activates the text field for editing. Upon activation, the text field\u0026rsquo;s contents are selected, making it so the user will fully re-enter the price each time. Keyboard is either decimal pad or number pad, depending on the locale being used. If the local doesn\u0026rsquo;t support decimal places with their currency (i.e. Japan), then there is no reason to present the decimal pad keyboard. ","permalink":"https://matfacer.com/posts/my-swiftui-currency-field/","summary":"\u003cp\u003eI\u0026rsquo;ve been spending a lot of time in SwiftUI lately and, so far, I love it.\u003c/p\u003e\n\u003cp\u003eWhile it is remarkably flexible and powerful, it is still very young. There are still pain points from what seems to be a lack of coverage in the framework. Worse still, because it is changing and updating so rapidly, I am finding that much advice on StackOverflow and many blog posts are outdated already.\u003c/p\u003e","title":"My SwiftUI Currency Field"},{"content":"Reinforcement learning is my area of focus so far when it comes to deep learning. RL is probably not the first stop for most on the machine learning education circuit, but it just happens to be where the problem I am trying to solve has taken me.\nWhen starting down the RL road, I was immediately confused by the concept of reward. Nothing was confusing about what it was - giving a dog a treat when it sits after you\u0026rsquo;ve asked it to sums things up pretty well. Instead, I was confused by its relation to the loss function. Both, at a high level, help inform when the correct thing is happening.\nRL primer Skip this if you\u0026rsquo;re already familiar with RL.\nIf you\u0026rsquo;re unfamiliar with reinforcement learning - things work a bit different from standard deep learning. There are similar concepts, but the terminology and applications have shifted somewhat. The purpose is to train an agent (think robot) to navigate an environment (play a game, or more generally, accomplish a task).\nNeural networks are still present in RL, but they are applied differently, and, in my experience so far, the emphasis is less on the NN and more on the environment. For example, there is a high-level wrapper library for RL, stable-baselines, which can handle all of the NN setups for you.\nThere is no dataset in reinforcement learning. Instead, you have an environment. To properly train your agent, you need to create a custom environment for your agent to interact. A standard template exists for creating custom environments. You need to describe the environment state, the agent\u0026rsquo;s allowed actions, and the reward for said actions.\nWhereas the goal of other types of ML is to minimize loss, the agent in RL is determined to maximize its reward. It will seek out ways to get the highest score possible.\nThat\u0026rsquo;s all for now!\nSwinging blind and striking out I jumped straight in, deciding not to get caught up too early by the nuances of reward vs. loss and see how far I could get with reward only. The answer? Not very!\nMy experiments focused mainly on rewarding the agent when closer to the desired goal than in the previous state. I played around with many different additional ideas surrounding this core concept.\nI realized a potential flaw in my strategies in that my reward scheme was not predictable enough. I couldn\u0026rsquo;t tell what the accumulated score meant. This idea came from the concept that the agent will seek to maximize its score. Therefore, it should be somewhat absolute and predictable.\nIn my next rounds of refining my rewards, I made an effort to incorporate this idea. I also borrowed some ideas from other environments I found in the OpenAI Gym. Still no significant improvements.\nRevisiting the original question With lots of experience in what isn\u0026rsquo;t working, I returned to my original query of the difference between loss and reward. Research revealed some interesting insights.\nIt turns out, what I was doing was something called reward shaping. It is not an evil concept or a bad thing but seems to get overused and easily abused. The description I read that helped most with bringing perspective was that in shaping the reward, you are slowly removing machine learning from the equation. Instead of the machine learning what to do, you are telling it what to do.\nWhile this idea may be too \u0026ldquo;ML purist,\u0026rdquo; it helped give a basis for understanding where rewards might have a limit and where loss might come back into the picture.\nHindsight experience replay This new information sent me down a new path of discovery. In reading more about reward shaping, I discovered hindsight experience replay (HER). It turns out, over-engineering reward schemas is a prevalent problem in RL, and HER is a more recent solution to help overcome the problem.\nEnvironments can quickly become very complex, making the agent receive a reward in extremely rare circumstances. When this happens, the agent doesn\u0026rsquo;t get rewarded, which means it doesn\u0026rsquo;t learn. The natural next step is to begin adding interim rewards, hoping to increase the reward frequency, so the agent learns.\nHER emulates a more human-like learning experience, where the agent will learn from its failures. I\u0026rsquo;ve read a great example: imagine you shoot a puck at a hockey net, and it goes wide to the right. Typical RL will assess the situation, see that you didn\u0026rsquo;t get the puck in the net, and not reward you. That is all you would know as the agent - \u0026ldquo;I didn\u0026rsquo;t get rewarded.\u0026rdquo;\nAs humans, we assess more from this scenario and understand more than just \u0026ldquo;I didn\u0026rsquo;t get rewarded.\u0026rdquo; We realize that we shot the puck wide and to the right, and so, therefore, next time, if I want to hit my goal, I should shoot more to the left.\nHER brings this same notion to RL, helping the agent learn not only from its successes but also from its failures. Using HER means reward shaping can then be reduced, and positive rewards can remain sparse.\nI tried implementing HER and did see some success, which was quite exciting. Still, my success was only peaking at around 50-60% in an environment I could not have simplified further.\nBack to custom loss Although I saw some signs of life from HER, the success rate in the most simplified environment possible was not enough. With plans to return to HER again later, it was time to return to a custom loss function.\nTo give some insight into my problem space, while keeping it minimal - I am working on solving point coordinates of a mesh. The predicted numbers have a special relationship, representing a mesh, and not considering this relationship will make those predictions less accurate.\nI installed PyTorch3D to leverage the mesh framework within, even though my problem is in 2D space, and it was quick and easy to create a custom loss function. I made the environment slightly more complicated once again and tried running my optimization loop. Keep in mind - this is not RL at this point, but instead just testing a theory on convergence for my problem, similar to PyTorch3D\u0026rsquo;s Fit Mesh tutorial. The result was great!\nWhat have I learned? We are now up to speed with where I am currently in my adventures. Through this process, I feel my understanding of loss vs. reward has improved, where I can at least now come up with a plan on how to employ both tools to work together on the same problem at the same time.\nHere is how I am summing things up for myself regarding loss and reward:\nLoss is like the game of hot and cold. It measures relativity, and it helps in the journey of getting to the goal. Reward is received for being in the desired state (or not). It is more absolute, and should be given sparingly. You can roughly fit both into the carrot and stick analogy if you squint your brain a bit.\nMy next steps are to provide even more complex examples to the current setup to stress test further, then return to RL to create an agent and environment to deploy this solution, hopefully.\nMy learnings are still a WIP, obviously, so there is a possibility I\u0026rsquo;m still off. I\u0026rsquo;ll aim to update again later with however things progress.\n","permalink":"https://matfacer.com/posts/loss-vs-reward-in-reinforcement-learning/","summary":"\u003cp\u003eReinforcement learning is my area of focus so far when it comes to deep learning. RL is probably not the first stop for most on the machine learning education circuit, but it just happens to be where the problem I am trying to solve has taken me.\u003c/p\u003e\n\u003cp\u003eWhen starting down the RL road, I was immediately confused by the concept of reward. Nothing was confusing about what it was - giving a dog a treat when it sits after you\u0026rsquo;ve asked it to sums things up pretty well. Instead, I was confused by its relation to the loss function. Both, at a high level, help inform when the correct thing is happening.\u003c/p\u003e","title":"Loss vs. reward in reinforcement learning"},{"content":"My journey into machine learning is still in its relatively early stages. I began by familiarizing myself with Tensorflow. It was an excellent introduction, whetting my appetite for AI, but I am now ready to make the switch to PyTorch.\nThere are two key drivers behind my decision to make this change.\nDebugging Process transparency Debugging Debugging in Tensorflow has been problematic, to say the least, being most painful when writing custom loss functions. I\u0026rsquo;d feed dummy data to the loss function while writing it, pre-vetting what I was creating. However, when something didn\u0026rsquo;t work as expected during training, troubleshooting was near impossible. Tensors at training time are opaque, acting in some \u0026ldquo;virtual\u0026rdquo; fashion if my memory serves (this was a while ago now).\nWhile I could throw down a breakpoint and inspect the values or print them out when I was \u0026ldquo;pre-vetting,\u0026rdquo; this \u0026ldquo;virtual\u0026rdquo; tensor removed any ability to do so. Perhaps this is possible to do, and I just hadn\u0026rsquo;t dug deep enough to discover how. I did dig mighty deep, though - so much so that it isn\u0026rsquo;t worth the effort even if it is possible.\nOn the other hand, PyTorch maintains a reputation of operating much closer to native Python, interfacing more cleanly with NumPy, and being a friendlier experience when debugging.\nProcess transparency Deep learning and neural nets have a steep learning curve, with many moving pieces and new concepts to understand (which can be intimidating). Tensorflow, and more specifically Keras, help reduce the barrier to entry by being a high-level wrapper, simplifying and removing the need for understanding some of the details of the underlying process. The structure for assembling a graph is apparent and feels guided, giving a clear template to follow to get results quickly.\nAfter much reading and researching, I feel I am now over the initial hump of bewilderment and have a decent grasp of most of the inner workings of the training process. It feels like a good time to expose myself to a new library in hopes of validating and cementing my understandings. PyTorch feels, so far, like it shares more of what Keras is hiding and is slightly less structured. Seeing and working with more of the moving pieces is an exciting next step.\nFor anyone out there also looking to break into PyTorch as a learning framework, I\u0026rsquo;ve found the following article to give a nicely pared-down view of the PyTorch life-cycle: PyTorch Tutorial: How to Develop Deep Learning Models with Python. Instead of walking you through a completed example, introducing too much additional information too soon and making things cloudy, It strips away everything non-essential. It gives you a look at the core process, leaving you with an easily digestible overview of the abstracted process.\nIn closing I\u0026rsquo;ve immensely enjoyed working with Tensorflow and Keras and may find myself returning to it someday. For now, I am excited to continue my journey with PyTorch and see how different the experience is.\n","permalink":"https://matfacer.com/posts/tensorflow-to-pytorch/","summary":"\u003cp\u003eMy journey into machine learning is still in its relatively early stages. I began by familiarizing myself with Tensorflow. It was an excellent introduction, whetting my appetite for AI, but I am now ready to make the switch to PyTorch.\u003c/p\u003e\n\u003cp\u003eThere are two key drivers behind my decision to make this change.\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eDebugging\u003c/li\u003e\n\u003cli\u003eProcess transparency\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"debugging\"\u003eDebugging\u003c/h2\u003e\n\u003cp\u003eDebugging in Tensorflow has been problematic, to say the least, being most painful when writing custom loss functions. I\u0026rsquo;d feed dummy data to the loss function while writing it, pre-vetting what I was creating. However, when something didn\u0026rsquo;t work as expected during training, troubleshooting was near impossible. Tensors at training time are opaque, acting in some \u0026ldquo;virtual\u0026rdquo; fashion if my memory serves (this was a while ago now).\u003c/p\u003e","title":"Tensorflow to PyTorch"},{"content":"I have been dabbling in deep learning recently, and I have completed a few courses and read through and watched many resources during that time. It can be hard to find good help, so I wanted to share my experience with Kaggle quickly.\nIf you\u0026rsquo;re not familiar with Kaggle, it is an excellent source of datasets for training your models. I believe this is what they are most well known for. They also have a complete set of courses relating to many things data science-related. The topics include data visualization, how to use the Pandas library, and more.\nAt the time of this writing, I have completed four courses with Kaggle. The experience has been great. The lessons use their own notebooks platform, presenting the material clearly and in bite-sized pieces. There is a read-only lesson, briefly going over the main ideas for each module, which includes examples. Then there is an interactive, hands-on half to each module, where you apply the concepts yourself.\nThe interactive lessons present many little puzzles to solve, grounded in practicality as things you might experience in a real-world scenario. They are all within your ability to solve, and they provide you with a hint and even the entire solution if needed. It is best to attempt to find the answer yourself, of course. They utilize binders to take care of much of the boilerplate so you stay focused on the concepts in the lesson, and they provide a custom module that gives you feedback on your attempted answers.\nIf you\u0026rsquo;re new to machine learning and aren\u0026rsquo;t too sure where to start, give Kaggle a try. I wish I had sooner.\nhttps://www.kaggle.com/learn\n","permalink":"https://matfacer.com/posts/kaggle-courses/","summary":"\u003cp\u003eI have been dabbling in deep learning recently, and I have completed a few courses and read through and watched many resources during that time. It can be hard to find good help, so I wanted to share my experience with Kaggle quickly.\u003c/p\u003e\n\u003cp\u003eIf you\u0026rsquo;re not familiar with Kaggle, it is an excellent source of datasets for training your models. I believe this is what they are most well known for. They also have a complete set of courses relating to many things data science-related. The topics include data visualization, how to use the Pandas library, and more.\u003c/p\u003e","title":"Kaggle Courses"},{"content":"The logging module, while something I’ve been using for years, is not something I can say I’ve been clear on. I’ve dug in more recently and thought I would share some quick learnings.\nLogger Hierarchy The first item to note is that Python’s logging module behaves as an inheritance hierarchy. This hierarchy will automatically kick in by using dot notation in the naming of your logger. For example, “eh.bee.sea” inherits from “eh.bee”, which inherits from “eh”.\nThat should help explain why you will see the following line in most places utilizing the logging module.\nlog = logging.getLogger(__name__)\nThis code will…\nAttempt to grab a logger instance, from a globally cached collection of loggers, by using the current module’s name. Create a new logger if it can’t find an already existing one using the name provided. Inherit the configuration for the new logger from any existing loggers that will be parents, Store this new logger instance in the global cache for future lookup. The beauty of this code is, it’s the same no matter where you are in your codebase. It is the hierarchy magic that makes it all work.\nMake Your Own I\u0026rsquo;ve found the way to get this working best is to configure your logger inside the __init__.py of your highest level Python package. Doing this will get the logger using the package\u0026rsquo;s name, leaving out \u0026quot;__init__\u0026quot;.\nFor example, if you run logging.getLogger(__name__) in my_package/__init__.py, it will create a logger by the name “my_package.”\nThat means you can then run log = logging.getLogger(__name__) in any submodules or packages under my_package, and it will inherit that initial configuration you made.\nMaya\u0026rsquo;s Root Logger The root logger, at the very top of the logging hierarchy, is already pre-configured with a log handler from Autodesk. This handler is what prints output to Maya\u0026rsquo;s script editor and formats it how it does.\nThe main thing to note here is, when implementing your own logger and custom handlers, there is no need to set up output to the script editor. The root logger already handles this functionality, which you will be inheriting from.\n","permalink":"https://matfacer.com/posts/demystifying-python-logging-in-maya/","summary":"\u003cp\u003eThe logging module, while something I’ve been using for years, is not something I can say I’ve been clear on. I’ve dug in more recently and thought I would share some quick learnings.\u003c/p\u003e\n\u003ch2 id=\"logger-hierarchy\"\u003eLogger Hierarchy\u003c/h2\u003e\n\u003cp\u003eThe first item to note is that Python’s logging module behaves as an inheritance hierarchy. This hierarchy will automatically kick in by using dot notation in the naming of your logger. For example, \u003cem\u003e“eh.bee.sea”\u003c/em\u003e inherits from \u003cem\u003e“eh.bee”\u003c/em\u003e, which inherits from \u003cem\u003e“eh”\u003c/em\u003e.\u003c/p\u003e","title":"Python logging in Maya"},{"content":"Recently, I completed the Applied Software Development part-time studies program at BCIT. It has been a three-year journey, and so I thought I would do a quick write-up about some of my favourite courses and my takeaways.\nWhy go back to school? I had been established in the industry for over ten years, was well experienced with Python, and had some experience in other languages. Why go back to school? Well, I was entirely self-taught through my years on the job.\nI came to the point in my career where I started viewing my self-teachings as only forming an opinion, to put it bluntly. Imagine reading the pages of a novel in a random order, absorbing small, disconnected plot points, trying to piece together the bigger story. I wanted to make sure I was understanding the story correctly and didn\u0026rsquo;t miss any critical early pages.\nWhat if I learned nothing new? Well, I didn’t know what I didn’t know. If it turned out there was nothing new to learn, at least now I’d know that and formal education would validate and reinforce my “opinions”. I saw it as a no-lose decision.\nIntroduction to Software Development 1 \u0026amp; 2 These were the first courses I took, naturally. They mainly covered the basics I was already familiar with, but there were still some excellent takeaways from the lessons.\nI got exposure to a new language with Java. While it probably won’t be my first choice of language to use for anything in the future, it was great to see familiar concepts in yet another language.\nThe more restrictive nature of Java was refreshing and opened my eyes, making me more critical of my beloved Python. Going through exercises for public/private access with inheritance helped me realize problematic design scenarios in Python that you can’t even create in Java. The beauty of Python’s openness is a double-edged sword and is something I might talk more about in the future.\nWell-known design acronyms, SOLID and DRY, were covered in the course. There was an entire class dedicated to going over each letter and thoroughly explaining them, with examples. Dry material for some, I’m sure, but a solid topic not likely to come up in self-taught adventures.\nBusiness Analysis and Systems Design This course was excellent. Systems Engineering is something I had stumbled across a year earlier and was doing a thorough analysis into, so this course was right up my alley.\nFor anyone unfamiliar, this is all about discovering requirements and designing a solution for said requirements. There are lots of tools, processes, and diagrams to help with this. Many developers might prefer to skip these things and get straight to the fun stuff, but it is super important and can make the fun stuff more fun.\nFocus and effort here will lead to higher quality solutions, better communication, and shared understanding. I would even argue reduced development costs as an outcome sometimes for having less confusion in the development cycle.\nAgile Methods and the Scrum Framework I thought this course was outstanding, and it might have been my favourite course in the program. It featured many lectures, thoroughly covering Agile concepts and tackling many of the misunderstandings about Agile. It continued with a multi-week role play in a team that featured oft-changing requirements and a last class multi-sprint simulation.\nThe teacher was super knowledgeable and passionate and made the entire course very engaging. Coming out of the 12 weeks, I felt I had a great handle on Agile and Scrum and came to love them as a way of working. Nicely thought-out artifacts and practices, done for specific reasons, all make essential contributions to an enjoyable and effective way of working.\niOS Mobile App Development This course was fun. Since I started the program, I had been looking forward to taking it. I had done some app development many years ago when Swift was still in its infancy, being at version 1. I loved making my app, but dealing with the quirks of a brand new language was too tedious.\nNow that Swift has matured, it’s super nice to work with. The course covered a large amount of content, and it was almost like a language immersion school. They staggered deadlines and critical dates for different things every week, meaning there was rarely a day off from studying in some capacity. It helped a lot with the absorption of course material.\nThe course also incorporated several other platforms into its tech stack and way of working, which none of the other courses had done. It was refreshing. The most mentionable being GitHub Classroom. Git has been my VCS of choice for a long time at home, but having worked somewhere for nearly a decade married to Perforce, I hadn\u0026rsquo;t experienced Git in a proper collaborative environment. This class was now that opportunity, and it was a great experience. Combine this with more lessons and experience with Git since the course finished, and it is hands down the winning VCS in my eyes.\nBack to Swift. It is such a great language. It feels very polished today, and Apple has significantly reduced the number of language gaps needing Objective-C syntax to come to the rescue. Swift might be my favourite language, from an appreciation standpoint, although it is difficult for me to dethrone Python since I use it every day. It’s just, Swift has the similar niceties and simplicity of Python but also addresses several of the weak points of Python, such as being a strongly typed language. Maybe it is just the benefit of being a more modern language? If you watch the WWDC presentation on SwiftUI, the new GUI framework for Swift, you’ll see how exciting the future of Swift is looking.\nThis course receives top marks from me. I had high hopes going in, and it met all of them. I felt confident coming out of it with my ability to create an app. There is little mystery to me now, and I am excited about creating one. I plan to spend my free time at home doing this, so there might be some posts appearing on here regarding Swift and app development soon, as I continue.\nTakeaways I feel accomplished in strengthening my foundational knowledge, and I’m pleased I dedicated my time to this. To anyone else who is self-taught and considering pursuing something similar, I recommend going after it. You don’t need to complete an entire program like I did (after all, it’s just a piece of paper), but at least get started with a course or two to find out what you don’t know you don’t know.\n","permalink":"https://matfacer.com/posts/applied-software-development-retrospective/","summary":"\u003cp\u003eRecently, I completed the Applied Software Development part-time studies program at BCIT. It has been a three-year journey, and so I thought I would do a quick write-up about some of my favourite courses and my takeaways.\u003c/p\u003e\n\u003ch2 id=\"why-go-back-to-school\"\u003eWhy go back to school?\u003c/h2\u003e\n\u003cp\u003eI had been established in the industry for over ten years, was well experienced with Python, and had some experience in other languages. Why go back to school? Well, I was entirely self-taught through my years on the job.\u003c/p\u003e","title":"Applied Software Development Retrospective"},{"content":"The __new__ method is a special method for Python classes. It is essentially the constructor for your class and handles its creation. You may think this is what the __init__ method is for, but the class instance (referred to from here out as \u0026ldquo;object\u0026rdquo;) is actually already created by the time __init__ gets called. The __init__ method is just setting initial values for an already created object. The __new__ method is what gets called before the object exists and actually creates and returns the object.\nThis concept can be a bit confusing at first. A better way of understanding might be through example.\nclass Sphere(object): pass class Cube(object): def __new__(cls, *args, **kwargs): return object.__new__(Sphere, *args, **kwargs) obj = Cube() print \u0026#34;My cube object is of type: %s\u0026#34; % type(obj) Here is the most basic and obvious example of what __new__ does. If you run this code, you will see that your cube is actually a sphere. The __new__ method of the Cube class is being overridden. If I were to not override the method, the code inside would essentially look like this:\nreturn object.__new__(cls, *args, **kwargs) If you examine the two lines you will see that the only change I have made is replacing cls with the class of my choosing, Sphere. The variable cls is just the class that was passed in to the __new__ method to be used when creating the object. In this case it would have been Cube.\nNow that we have a very basic explanation of this handy method out of the way, how can it be used?\nFactories The best application I have found for the __new__ method is to be used as a factory to automatically build other classes. For example, I was writing my own wrapper for Maya Python and wanted it so when I created an instance of my main \u0026ldquo;Maya Node\u0026rdquo; wrapper class it would automatically return a sub-class depending on the type of node. If the node was a joint, it would return a JointWrapper object instead of a MayaNode object. I have since switched over to using PyMel and discovered it is doing the same thing.\nAnother example of this factory approach is for versioning a rig wrapper class for interacting with my rigs. This is something I did recently. I stored a version number on my rig in Maya and then had a series of wrapper classes for it: RigWrapper, RigWrapper_2, RigWrapper_2_01, RigWrapper_3, etc. Each of these rig wrapper \u0026ldquo;versions\u0026rdquo; would inherit from the previous. Inside the __new__ method on the original RigWrapper class I had code that would get the version number stored on the rig in the scene and then do an introspection of the file to find all other versions of the RigWrapper class. It would then do a comparison of these classes names to find the closest version without rounding up (if the rig in Maya was version 2.9 it would use RigWrapper_2_01 rather than RigWrapper_3). This is the class it would then use to create and return. The rig would be correctly wrapped with the appropriate version of the wrapper class; you can call RigWrapper(\u0026lsquo;ctrl_master\u0026rsquo;) and it will return an instance of RigWrapper_2_01.\nThis was powerful because it brought all the features of inheritance to my rigging interface while also being very simple to use. It allowed me to make major changes to my rigs with little concern for them breaking because of incompatibility with the tools. As long as my tools for the rigs were using the RigWrapper class it would get the correct wrapper class and work as expected, and I didn\u0026rsquo;t have to do any extra work at this point in order to find which wrapper to use. All the work was already done.\nSingletons Every once in a while you might come across an instance where you might want a class to ever be able to be created once. Nine times out of ten this probably means you should be breaking this code out to its own module, but there is still that odd time that you might have reason not to. You can use the __new__ method to make it so your class only ever gets created once. Here is example code for this:\nclass Singleton(object): _instance = None def __init__(self, *args, **kwargs): # Init will always be called, so check if it has already been initialized by whether there is already an instance stored. if self.__class__._instance: return else: # If there is no instance stored, store this instance for next time. self.__class__._instance = self # Carry on with whatever initialization you want to have happen. self._whatever = True def __new__(cls, *args, **kwargs): if cls._instance: return cls._instance else: return object.__new__(cls, *args, **kwargs) Validation I have done this before, but I cannot fully endorse this as it creates some strange and unexpected behaviour. It is not illegal and is supported by Python, but it just doesn\u0026rsquo;t feel right. Doing a quick search about it on Stack Overflow showed shared sentiments from others. What I am talking about is doing validation checks in __new__ and returning None if those checks are not met.\nThe reason this makes for unexpected and strange behaviour is that if you are creating an instance of a class, you are expecting an instance of that class to be returned. Having it return None instead is unpredictable and weird. This is a very good reason not to do this.\nYou can also make an argument for this, although I do not feel it beats the argument against doing this. Imagine the scenario of creating a class that requires a file path to be created. If this class is passed a path to a file that doesn\u0026rsquo;t exist, the class will be useless and will error when its functions are called. You could do a os.path.exists in the __new__ and if it fails return None rather than creating the class. Then before you start calling any of its functions just check to make sure the class instance is equal to something. If you are creating many instances of this class and collect them in a list, you can filter the list to remove any None objects. This would ensure any object that is successfully created with the class will be working and be associated with a file on disk.\nThe alternative to this would be creating a function in the class called isValid or doesFileExist, or something similar. Before calling a function that requires the file to exist, call this function just to ensure that it does. This is a lot more clear since you will have a function stating exactly what is happening, rather than you just magically getting None returned. It isn\u0026rsquo;t quite as clean though since you will be having checks all over the place to make sure the file exists. It would be easier if the class just never exists if the file doesn\u0026rsquo;t exist.\nIn the end, this validation approach is a very grey area. I\u0026rsquo;m not really all that keen on one approach over another. The jury is still out on this one for me. Not a huge fan though.\nIt would be great to hear if anyone out there is using __new__ in other ways. These are just the uses I have found for it, but I am sure there are many other great applications.\n","permalink":"https://matfacer.com/posts/using-the-__new__-method-in-python-classes/","summary":"\u003cp\u003eThe __new__ method is a special method for Python classes. It is essentially the constructor for your class and handles its creation. You may think this is what the __init__ method is for, but the class instance (referred to from here out as \u0026ldquo;object\u0026rdquo;) is actually already created by the time __init__ gets called. The __init__ method is just setting initial values for an already created object. The __new__ method is what gets called before the object exists and actually creates and returns the object.\u003c/p\u003e","title":"Using the __new__ method in Python classes"}]